mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8227275: Within native OOM error handling, assertions may hang the process
Reviewed-by: mdoerr, coleenp
This commit is contained in:
parent
4b5b4f479c
commit
ac0e72332e
10 changed files with 40 additions and 15 deletions
|
@ -132,8 +132,9 @@ static void crash_handler(int sig, siginfo_t* info, void* ucVoid) {
|
||||||
// Needed because asserts may happen in error handling too.
|
// Needed because asserts may happen in error handling too.
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // CAN_SHOW_REGISTERS_ON_ASSERT
|
#endif // CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
|
|
||||||
|
|
|
@ -279,8 +279,9 @@ JVM_handle_linux_signal(int sig,
|
||||||
|
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -301,8 +301,9 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
|
||||||
|
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -271,8 +271,9 @@ JVM_handle_linux_signal(int sig,
|
||||||
|
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -270,8 +270,9 @@ JVM_handle_linux_signal(int sig,
|
||||||
|
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -514,8 +514,9 @@ JVM_handle_linux_signal(int sig,
|
||||||
|
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -303,8 +303,9 @@ JVM_handle_linux_signal(int sig,
|
||||||
|
|
||||||
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
|
||||||
handle_assert_poison_fault(ucVoid, info->si_addr);
|
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -734,6 +734,10 @@ void initialize_assert_poison() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void disarm_assert_poison() {
|
||||||
|
g_assert_poison = &g_dummy;
|
||||||
|
}
|
||||||
|
|
||||||
static void store_context(const void* context) {
|
static void store_context(const void* context) {
|
||||||
memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
|
memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
|
||||||
#if defined(__linux) && defined(PPC64)
|
#if defined(__linux) && defined(PPC64)
|
||||||
|
@ -746,7 +750,14 @@ static void store_context(const void* context) {
|
||||||
bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
|
bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
|
||||||
if (faulting_address == g_assert_poison) {
|
if (faulting_address == g_assert_poison) {
|
||||||
// Disarm poison page.
|
// Disarm poison page.
|
||||||
os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX);
|
if (os::protect_memory((char*)g_assert_poison, os::vm_page_size(), os::MEM_PROT_RWX) == false) {
|
||||||
|
#ifdef ASSERT
|
||||||
|
fprintf(stderr, "Assertion poison page cannot be unprotected - mprotect failed with %d (%s)",
|
||||||
|
errno, os::strerror(errno));
|
||||||
|
fflush(stderr);
|
||||||
|
#endif
|
||||||
|
return false; // unprotecting memory may fail in OOM situations, as surprising as this sounds.
|
||||||
|
}
|
||||||
// Store Context away.
|
// Store Context away.
|
||||||
if (ucVoid) {
|
if (ucVoid) {
|
||||||
const intx my_tid = os::current_thread_id();
|
const intx my_tid = os::current_thread_id();
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
extern char* g_assert_poison;
|
extern char* g_assert_poison;
|
||||||
#define TOUCH_ASSERT_POISON (*g_assert_poison) = 'X';
|
#define TOUCH_ASSERT_POISON (*g_assert_poison) = 'X';
|
||||||
void initialize_assert_poison();
|
void initialize_assert_poison();
|
||||||
|
void disarm_assert_poison();
|
||||||
bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address);
|
bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address);
|
||||||
#else
|
#else
|
||||||
#define TOUCH_ASSERT_POISON
|
#define TOUCH_ASSERT_POISON
|
||||||
|
|
|
@ -1327,6 +1327,12 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt
|
||||||
// File descriptor to the error log file.
|
// File descriptor to the error log file.
|
||||||
static int fd_log = -1;
|
static int fd_log = -1;
|
||||||
|
|
||||||
|
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
|
||||||
|
// Disarm assertion poison page, since from this point on we do not need this mechanism anymore and it may
|
||||||
|
// cause problems in error handling during native OOM, see JDK-8227275.
|
||||||
|
disarm_assert_poison();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Use local fdStream objects only. Do not use global instances whose initialization
|
// Use local fdStream objects only. Do not use global instances whose initialization
|
||||||
// relies on dynamic initialization (see JDK-8214975). Do not rely on these instances
|
// relies on dynamic initialization (see JDK-8214975). Do not rely on these instances
|
||||||
// to carry over into recursions or invocations from other threads.
|
// to carry over into recursions or invocations from other threads.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue