< 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 >