hotspot/src/os/bsd/vm/vmError_bsd.cpp
changeset 28943 679546f0cc1f
parent 10565 dc90c239f4ec
child 29573 2d800e5d575f
--- a/hotspot/src/os/bsd/vm/vmError_bsd.cpp	Wed Feb 04 16:09:49 2015 +0100
+++ b/hotspot/src/os/bsd/vm/vmError_bsd.cpp	Wed Feb 04 18:47:42 2015 -0500
@@ -63,9 +63,15 @@
   } while (yes);
 }
 
+// handle all synchronous program error signals which may happen during error
+// reporting. They must be unblocked, caught, handled.
+
+static const int SIGNALS[] = { SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGTRAP }; // add more if needed
+static const int NUM_SIGNALS = sizeof(SIGNALS) / sizeof(int);
+
 // Space for our "saved" signal flags and handlers
-static int resettedSigflags[2];
-static address resettedSighandler[2];
+static int resettedSigflags[NUM_SIGNALS];
+static address resettedSighandler[NUM_SIGNALS];
 
 static void save_signal(int idx, int sig)
 {
@@ -78,19 +84,19 @@
 }
 
 int VMError::get_resetted_sigflags(int sig) {
-  if(SIGSEGV == sig) {
-    return resettedSigflags[0];
-  } else if(SIGBUS == sig) {
-    return resettedSigflags[1];
+  for (int i = 0; i < NUM_SIGNALS; i++) {
+    if (SIGNALS[i] == sig) {
+      return resettedSigflags[i];
+    }
   }
   return -1;
 }
 
 address VMError::get_resetted_sighandler(int sig) {
-  if(SIGSEGV == sig) {
-    return resettedSighandler[0];
-  } else if(SIGBUS == sig) {
-    return resettedSighandler[1];
+  for (int i = 0; i < NUM_SIGNALS; i++) {
+    if (SIGNALS[i] == sig) {
+      return resettedSighandler[i];
+    }
   }
   return NULL;
 }
@@ -100,16 +106,25 @@
   sigset_t newset;
   sigemptyset(&newset);
   sigaddset(&newset, sig);
-  sigprocmask(SIG_UNBLOCK, &newset, NULL);
+  // also unmask other synchronous signals
+  for (int i = 0; i < NUM_SIGNALS; i++) {
+    sigaddset(&newset, SIGNALS[i]);
+  }
+  pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
 
   VMError err(NULL, sig, NULL, info, ucVoid);
   err.report_and_die();
 }
 
 void VMError::reset_signal_handlers() {
-  // Save sigflags for resetted signals
-  save_signal(0, SIGSEGV);
-  save_signal(1, SIGBUS);
-  os::signal(SIGSEGV, CAST_FROM_FN_PTR(void *, crash_handler));
-  os::signal(SIGBUS, CAST_FROM_FN_PTR(void *, crash_handler));
+  // install signal handlers for all synchronous program error signals
+  sigset_t newset;
+  sigemptyset(&newset);
+
+  for (int i = 0; i < NUM_SIGNALS; i++) {
+    save_signal(i, SIGNALS[i]);
+    os::signal(SIGNALS[i], CAST_FROM_FN_PTR(void *, crash_handler));
+    sigaddset(&newset, SIGNALS[i]);
+  }
+  pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
 }