< prev index next >

src/os/solaris/vm/vmError_solaris.cpp

Print this page
rev 7758 : 8065895 Synchronous signals during error reporting may terminate or hang VM process
Reviewed-by: dholmes,gziemski
Contributed-by: stuefe

*** 28,37 **** --- 28,38 ---- #include "runtime/thread.hpp" #include "utilities/vmError.hpp" #include <sys/types.h> #include <sys/wait.h> + #include <thread.h> #include <signal.h> void VMError::show_message_box(char *buf, int buflen) { bool yes; do {
*** 57,69 **** yes = false; } } while (yes); } // Space for our "saved" signal flags and handlers ! static int resettedSigflags[2]; ! static address resettedSighandler[2]; static void save_signal(int idx, int sig) { struct sigaction sa; sigaction(sig, NULL, &sa); --- 58,76 ---- yes = false; } } 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[NUM_SIGNALS]; ! static address resettedSighandler[NUM_SIGNALS]; static void save_signal(int idx, int sig) { struct sigaction sa; sigaction(sig, NULL, &sa);
*** 72,111 **** ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) : CAST_FROM_FN_PTR(address, sa.sa_handler); } int VMError::get_resetted_sigflags(int sig) { ! if(SIGSEGV == sig) { ! return resettedSigflags[0]; ! } else if(SIGBUS == sig) { ! return resettedSigflags[1]; } return -1; } address VMError::get_resetted_sighandler(int sig) { ! if(SIGSEGV == sig) { ! return resettedSighandler[0]; ! } else if(SIGBUS == sig) { ! return resettedSighandler[1]; } return NULL; } static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { // unmask current signal sigset_t newset; sigemptyset(&newset); sigaddset(&newset, sig); ! sigprocmask(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)); } --- 79,127 ---- ? CAST_FROM_FN_PTR(address, sa.sa_sigaction) : CAST_FROM_FN_PTR(address, sa.sa_handler); } int VMError::get_resetted_sigflags(int sig) { ! for (int i = 0; i < NUM_SIGNALS; i++) { ! if (SIGNALS[i] == sig) { ! return resettedSigflags[i]; ! } } return -1; } address VMError::get_resetted_sighandler(int sig) { ! for (int i = 0; i < NUM_SIGNALS; i++) { ! if (SIGNALS[i] == sig) { ! return resettedSighandler[i]; ! } } return NULL; } static void crash_handler(int sig, siginfo_t* info, void* ucVoid) { // unmask current signal sigset_t newset; sigemptyset(&newset); sigaddset(&newset, sig); ! // also unmask other synchronous signals ! for (int i = 0; i < NUM_SIGNALS; i++) { ! sigaddset(&newset, SIGNALS[i]); ! } ! thr_sigsetmask(SIG_UNBLOCK, &newset, NULL); VMError err(NULL, sig, NULL, info, ucVoid); err.report_and_die(); } void VMError::reset_signal_handlers() { ! // 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]); ! } ! thr_sigsetmask(SIG_UNBLOCK, &newset, NULL); }
< prev index next >