--- old/src/os/bsd/vm/vmError_bsd.cpp 2014-11-26 07:18:29.132150000 +0100 +++ new/src/os/bsd/vm/vmError_bsd.cpp 2014-11-26 07:18:28.492083000 +0100 @@ -63,9 +63,21 @@ } while (yes); } +// handle all synchronous program error signals which may happen during error +// reporting. They must be unblocked, caught, handled. +// +// Note that in the hotspot signal handlers are installed with a fully filled +// signal mask, i.e. upon delivery all signals - also synchronous error signals +// - are blocked. For synchronous error signals this is deadly - program will +// hang or be ended immediately if secondary errors happend during error +// reporting. + +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 +90,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 +112,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); }