< prev index next >
src/os/bsd/vm/vmError_bsd.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
*** 61,73 ****
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);
--- 61,79 ----
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);
*** 76,115 ****
? 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));
}
--- 82,130 ----
? 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]);
! }
! pthread_sigmask(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]);
! }
! pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
}
< prev index next >