8227275: Within native OOM error handling, assertions may hang the process
authorstuefe
Thu, 11 Jul 2019 06:56:51 +0200
changeset 55653 3243c42d737d
parent 55652 2d1acda7555a
child 55654 92ab031d6540
8227275: Within native OOM error handling, assertions may hang the process Reviewed-by: mdoerr, coleenp
src/hotspot/os/posix/vmError_posix.cpp
src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp
src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp
src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp
src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp
src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp
src/hotspot/share/utilities/debug.cpp
src/hotspot/share/utilities/debug.hpp
src/hotspot/share/utilities/vmError.cpp
--- a/src/hotspot/os/posix/vmError_posix.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os/posix/vmError_posix.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -132,8 +132,9 @@
   // Needed because asserts may happen in error handling too.
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return;
+    }
   }
 #endif // CAN_SHOW_REGISTERS_ON_ASSERT
 
--- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -279,8 +279,9 @@
 
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return 1;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return 1;
+    }
   }
 #endif
 
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -301,8 +301,9 @@
 
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return 1;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return 1;
+    }
   }
 #endif
 
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -271,8 +271,9 @@
 
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return 1;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return 1;
+    }
   }
 #endif
 
--- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -270,8 +270,9 @@
 
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return 1;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return 1;
+    }
   }
 #endif
 
--- a/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os_cpu/linux_sparc/os_linux_sparc.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -514,8 +514,9 @@
 
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return 1;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return 1;
+    }
   }
 #endif
 
--- a/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/os_cpu/linux_x86/os_linux_x86.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -303,8 +303,9 @@
 
 #ifdef CAN_SHOW_REGISTERS_ON_ASSERT
   if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
-    handle_assert_poison_fault(ucVoid, info->si_addr);
-    return 1;
+    if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
+      return 1;
+    }
   }
 #endif
 
--- a/src/hotspot/share/utilities/debug.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/share/utilities/debug.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -734,6 +734,10 @@
   }
 }
 
+void disarm_assert_poison() {
+  g_assert_poison = &g_dummy;
+}
+
 static void store_context(const void* context) {
   memcpy(&g_stored_assertion_context, context, sizeof(ucontext_t));
 #if defined(__linux) && defined(PPC64)
@@ -746,7 +750,14 @@
 bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address) {
   if (faulting_address == g_assert_poison) {
     // 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.
     if (ucVoid) {
       const intx my_tid = os::current_thread_id();
--- a/src/hotspot/share/utilities/debug.hpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/share/utilities/debug.hpp	Thu Jul 11 06:56:51 2019 +0200
@@ -37,6 +37,7 @@
 extern char* g_assert_poison;
 #define TOUCH_ASSERT_POISON (*g_assert_poison) = 'X';
 void initialize_assert_poison();
+void disarm_assert_poison();
 bool handle_assert_poison_fault(const void* ucVoid, const void* faulting_address);
 #else
 #define TOUCH_ASSERT_POISON
--- a/src/hotspot/share/utilities/vmError.cpp	Thu Jul 11 06:49:49 2019 +0200
+++ b/src/hotspot/share/utilities/vmError.cpp	Thu Jul 11 06:56:51 2019 +0200
@@ -1327,6 +1327,12 @@
   // File descriptor to the error log file.
   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
   // relies on dynamic initialization (see JDK-8214975). Do not rely on these instances
   // to carry over into recursions or invocations from other threads.