< prev index next >
src/os/linux/vm/vmError_linux.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,13 +61,19 @@
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[2];
-static address resettedSighandler[2];
+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,40 +82,50 @@
? 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];
+ 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;
}
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);
+ // 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);
+
}
< prev index next >