8255711: Fix and unify hotspot signal handlers

Reviewed-by: coleenp, gziemski, dholmes
This commit is contained in:
Thomas Stuefe 2020-11-09 12:03:06 +00:00
parent d99e1f6c29
commit dd8e4ffbe5
15 changed files with 270 additions and 853 deletions

View File

@ -21,7 +21,7 @@
# questions.
#
JVM_handle_linux_signal
JVM_handle_aix_signal
numa_error
numa_warn
sysThreadAvailableStackWithSlack

View File

@ -26,6 +26,7 @@
#include "jvm.h"
#include "logging/log.hpp"
#include "runtime/atomic.hpp"
#include "runtime/globals.hpp"
#include "runtime/interfaceSupport.inline.hpp"
#include "runtime/os.hpp"
@ -71,10 +72,6 @@ extern "C" {
static sigset_t check_signal_done;
static bool check_signals = true;
// This boolean allows users to forward their own non-matching signals
// to JVM_handle_bsd_signal/JVM_handle_linux_signal, harmlessly.
static bool signal_handlers_are_installed = false;
debug_only(static bool signal_sets_initialized = false);
static sigset_t unblocked_sigs, vm_sigs, preinstalled_sigs;
struct sigaction sigact[NSIG];
@ -261,6 +258,8 @@ static const struct {
{ -1, NULL }
};
static const char* get_signal_name(int sig, char* out, size_t outlen);
////////////////////////////////////////////////////////////////////////////////
// sun.misc.Signal support
@ -313,6 +312,8 @@ static int check_pending_signals() {
}
} while (threadIsSuspended);
}
ShouldNotReachHere();
return 0; // Satisfy compiler
}
int os::signal_wait() {
@ -408,50 +409,6 @@ bool PosixSignals::chained_handler(int sig, siginfo_t* siginfo, void* context) {
return chained;
}
////////////////////////////////////////////////////////////////////////////////
// signal handling (except suspend/resume)
// This routine may be used by user applications as a "hook" to catch signals.
// The user-defined signal handler must pass unrecognized signals to this
// routine, and if it returns true (non-zero), then the signal handler must
// return immediately. If the flag "abort_if_unrecognized" is true, then this
// routine will never retun false (zero), but instead will execute a VM panic
// routine kill the process.
//
// If this routine returns false, it is OK to call it again. This allows
// the user-defined signal handler to perform checks either before or after
// the VM performs its own checks. Naturally, the user code would be making
// a serious error if it tried to handle an exception (such as a null check
// or breakpoint) that the VM was generating for its own correct operation.
//
// This routine may recognize any of the following kinds of signals:
// SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1.
// It should be consulted by handlers for any of those signals.
//
// The caller of this routine must pass in the three arguments supplied
// to the function referred to in the "sa_sigaction" (not the "sa_handler")
// field of the structure passed to sigaction(). This routine assumes that
// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART.
//
// Note that the VM will print warnings if it detects conflicting signal
// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers".
//
#if defined(BSD)
extern "C" JNIEXPORT int JVM_handle_bsd_signal(int signo, siginfo_t* siginfo,
void* ucontext,
int abort_if_unrecognized);
#elif defined(AIX)
extern "C" JNIEXPORT int JVM_handle_aix_signal(int signo, siginfo_t* siginfo,
void* ucontext,
int abort_if_unrecognized);
#else
extern "C" JNIEXPORT int JVM_handle_linux_signal(int signo, siginfo_t* siginfo,
void* ucontext,
int abort_if_unrecognized);
#endif
///// Synchronous (non-deferrable) error signals (ILL, SEGV, FPE, BUS, TRAP):
// These signals are special because they cannot be deferred and, if they
@ -502,21 +459,151 @@ void PosixSignals::unblock_error_signals() {
::pthread_sigmask(SIG_UNBLOCK, &set, NULL);
}
// Renamed from 'signalHandler' to avoid collision with other shared libs.
static void javaSignalHandler(int sig, siginfo_t* info, void* uc) {
assert(info != NULL && uc != NULL, "it must be old kernel");
class ErrnoPreserver: public StackObj {
const int _saved;
public:
ErrnoPreserver() : _saved(errno) {}
~ErrnoPreserver() { errno = _saved; }
};
////////////////////////////////////////////////////////////////////////////////
// JVM_handle_(linux|aix|bsd)_signal()
// This routine is the shared part of the central hotspot signal handler. It can
// also be called by a user application, if a user application prefers to do
// signal handling itself - in that case it needs to pass signals the VM
// internally uses on to the VM first.
//
// The user-defined signal handler must pass unrecognized signals to this
// routine, and if it returns true (non-zero), then the signal handler must
// return immediately. If the flag "abort_if_unrecognized" is true, then this
// routine will never return false (zero), but instead will execute a VM panic
// routine to kill the process.
//
// If this routine returns false, it is OK to call it again. This allows
// the user-defined signal handler to perform checks either before or after
// the VM performs its own checks. Naturally, the user code would be making
// a serious error if it tried to handle an exception (such as a null check
// or breakpoint) that the VM was generating for its own correct operation.
//
// This routine may recognize any of the following kinds of signals:
// SIGBUS, SIGSEGV, SIGILL, SIGFPE, SIGQUIT, SIGPIPE, SIGXFSZ, SIGUSR1.
// It should be consulted by handlers for any of those signals.
//
// The caller of this routine must pass in the three arguments supplied
// to the function referred to in the "sa_sigaction" (not the "sa_handler")
// field of the structure passed to sigaction(). This routine assumes that
// the sa_flags field passed to sigaction() includes SA_SIGINFO and SA_RESTART.
//
// Note that the VM will print warnings if it detects conflicting signal
// handlers, unless invoked with the option "-XX:+AllowUserSignalHandlers".
//
#if defined(BSD)
#define JVM_HANDLE_XXX_SIGNAL JVM_handle_bsd_signal
#elif defined(AIX)
#define JVM_HANDLE_XXX_SIGNAL JVM_handle_aix_signal
#elif defined(LINUX)
#define JVM_HANDLE_XXX_SIGNAL JVM_handle_linux_signal
#else
#error who are you?
#endif
extern "C" JNIEXPORT
int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
void* ucVoid, int abort_if_unrecognized)
{
assert(info != NULL && ucVoid != NULL, "sanity");
// Note: it's not uncommon that JNI code uses signal/sigset to install,
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// this handler might be invoked with junk info/ucVoid. To avoid unnecessary
// crash when libjsig is not preloaded, try handle signals that do not require
// siginfo/ucontext first.
// Preserve errno value over signal handler.
// (note: RAII ok here, even with JFR thread crash protection, see below).
ErrnoPreserver ep;
// Unblock all synchronous error signals (see JDK-8252533)
PosixSignals::unblock_error_signals();
int orig_errno = errno; // Preserve errno value over signal handler.
#if defined(BSD)
JVM_handle_bsd_signal(sig, info, uc, true);
#elif defined(AIX)
JVM_handle_aix_signal(sig, info, uc, true);
#else
JVM_handle_linux_signal(sig, info, uc, true);
ucontext_t* const uc = (ucontext_t*) ucVoid;
Thread* const t = Thread::current_or_null_safe();
// Handle JFR thread crash protection.
// Note: this may cause us to longjmp away. Do not use any code before this
// point which really needs any form of epilogue code running, eg RAII objects.
os::ThreadCrashProtection::check_crash_protection(sig, t);
bool signal_was_handled = false;
// Handle assertion poison page accesses.
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
signal_was_handled = handle_assert_poison_fault(ucVoid, info->si_addr);
}
#endif
errno = orig_errno;
// Ignore SIGPIPE and SIGXFSZ (4229104, 6499219).
if (sig == SIGPIPE || sig == SIGXFSZ) {
PosixSignals::chained_handler(sig, info, ucVoid);
signal_was_handled = true; // unconditionally.
}
// Call platform dependent signal handler.
if (!signal_was_handled) {
JavaThread* const jt = (t != NULL && t->is_Java_thread()) ? (JavaThread*) t : NULL;
signal_was_handled = PosixSignals::pd_hotspot_signal_handler(sig, info, uc, jt);
}
// From here on, if the signal had not been handled, it is a fatal error.
// Give the chained signal handler - should it exist - a shot.
if (!signal_was_handled) {
signal_was_handled = PosixSignals::chained_handler(sig, info, ucVoid);
}
// Invoke fatal error handling.
if (!signal_was_handled && abort_if_unrecognized) {
// Extract pc from context for the error handler to display.
address pc = NULL;
if (uc != NULL) {
// prepare fault pc address for error reporting.
if (S390_ONLY(sig == SIGILL || sig == SIGFPE) NOT_S390(false)) {
pc = (address)info->si_addr;
} else {
pc = PosixSignals::ucontext_get_pc(uc);
}
}
#if defined(ZERO) && !defined(PRODUCT)
char buf[64];
VMError::report_and_die(t, sig, pc, info, ucVoid,
"\n#"
"\n# /--------------------\\"
"\n# | %-7s |"
"\n# \\---\\ /--------------/"
"\n# /"
"\n# [-] |\\_/| "
"\n# (+)=C |o o|__ "
"\n# | | =-*-=__\\ "
"\n# OOO c_c_(___)",
get_signal_name(sig, buf, sizeof(buf)));
#else
VMError::report_and_die(t, sig, pc, info, ucVoid);
#endif
// VMError should not return.
ShouldNotReachHere();
}
return signal_was_handled;
}
// Entry point for the hotspot signal handler.
static void javaSignalHandler(int sig, siginfo_t* info, void* ucVoid) {
// Do not add any code here!
// Only add code to either JVM_HANDLE_XXX_SIGNAL or PosixSignals::pd_hotspot_signal_handler.
(void)JVM_HANDLE_XXX_SIGNAL(sig, info, ucVoid, true);
}
static void UserHandler(int sig, void *siginfo, void *context) {
@ -766,9 +853,7 @@ void os::run_periodic_checks() {
do_signal_check(SIGBUS);
do_signal_check(SIGPIPE);
do_signal_check(SIGXFSZ);
#if defined(PPC64)
do_signal_check(SIGTRAP);
#endif
PPC64_ONLY(do_signal_check(SIGTRAP);)
// ReduceSignalUsage allows the user to override these handlers
// see comments at the very top and jvm_md.h
@ -935,7 +1020,6 @@ static bool is_valid_signal(int sig) {
#endif
}
// Returned string is a constant. For unknown signals "UNKNOWN" is returned.
static const char* get_signal_name(int sig, char* out, size_t outlen) {
const char* ret = NULL;
@ -1075,7 +1159,7 @@ int os::get_signal_number(const char* signal_name) {
return -1;
}
void set_signal_handler(int sig, bool set_installed) {
void set_signal_handler(int sig) {
// Check for overwrite.
struct sigaction oldAct;
sigaction(sig, (struct sigaction*)NULL, &oldAct);
@ -1086,7 +1170,7 @@ void set_signal_handler(int sig, bool set_installed) {
if (oldhand != CAST_FROM_FN_PTR(void*, SIG_DFL) &&
oldhand != CAST_FROM_FN_PTR(void*, SIG_IGN) &&
oldhand != CAST_FROM_FN_PTR(void*, (sa_sigaction_t)javaSignalHandler)) {
if (AllowUserSignalHandlers || !set_installed) {
if (AllowUserSignalHandlers) {
// Do not overwrite; user takes responsibility to forward to us.
return;
} else if (UseSignalChaining) {
@ -1103,13 +1187,8 @@ void set_signal_handler(int sig, bool set_installed) {
struct sigaction sigAct;
sigfillset(&(sigAct.sa_mask));
remove_error_signals_from_set(&(sigAct.sa_mask));
sigAct.sa_handler = SIG_DFL;
if (!set_installed) {
sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
} else {
sigAct.sa_sigaction = javaSignalHandler;
sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
}
sigAct.sa_sigaction = javaSignalHandler;
sigAct.sa_flags = SA_SIGINFO|SA_RESTART;
#if defined(__APPLE__)
// Needed for main thread as XNU (Mac OS X kernel) will only deliver SIGSEGV
// (which starts as SIGBUS) on main thread with faulting address inside "stack+guard pages"
@ -1136,87 +1215,75 @@ void set_signal_handler(int sig, bool set_installed) {
assert(oldhand2 == oldhand, "no concurrent signal handler installation");
}
// install signal handlers for signals that HotSpot needs to
// handle in order to support Java-level exception handling.
bool PosixSignals::are_signal_handlers_installed() {
return signal_handlers_are_installed;
}
// install signal handlers for signals that HotSpot needs to
// handle in order to support Java-level exception handling.
void PosixSignals::install_signal_handlers() {
if (!signal_handlers_are_installed) {
signal_handlers_are_installed = true;
// signal-chaining
typedef void (*signal_setting_t)();
signal_setting_t begin_signal_setting = NULL;
signal_setting_t end_signal_setting = NULL;
begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting"));
if (begin_signal_setting != NULL) {
end_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
dlsym(RTLD_DEFAULT, "JVM_end_signal_setting"));
get_signal_action = CAST_TO_FN_PTR(get_signal_t,
dlsym(RTLD_DEFAULT, "JVM_get_signal_action"));
libjsig_is_loaded = true;
assert(UseSignalChaining, "should enable signal-chaining");
}
if (libjsig_is_loaded) {
// Tell libjsig jvm is setting signal handlers
(*begin_signal_setting)();
}
// signal-chaining
typedef void (*signal_setting_t)();
signal_setting_t begin_signal_setting = NULL;
signal_setting_t end_signal_setting = NULL;
begin_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
dlsym(RTLD_DEFAULT, "JVM_begin_signal_setting"));
if (begin_signal_setting != NULL) {
end_signal_setting = CAST_TO_FN_PTR(signal_setting_t,
dlsym(RTLD_DEFAULT, "JVM_end_signal_setting"));
get_signal_action = CAST_TO_FN_PTR(get_signal_t,
dlsym(RTLD_DEFAULT, "JVM_get_signal_action"));
libjsig_is_loaded = true;
assert(UseSignalChaining, "should enable signal-chaining");
}
if (libjsig_is_loaded) {
// Tell libjsig jvm is setting signal handlers
(*begin_signal_setting)();
}
set_signal_handler(SIGSEGV, true);
set_signal_handler(SIGPIPE, true);
set_signal_handler(SIGBUS, true);
set_signal_handler(SIGILL, true);
set_signal_handler(SIGFPE, true);
#if defined(PPC64) || defined(AIX)
set_signal_handler(SIGTRAP, true);
#endif
set_signal_handler(SIGXFSZ, true);
set_signal_handler(SIGSEGV);
set_signal_handler(SIGPIPE);
set_signal_handler(SIGBUS);
set_signal_handler(SIGILL);
set_signal_handler(SIGFPE);
PPC64_ONLY(set_signal_handler(SIGTRAP);)
set_signal_handler(SIGXFSZ);
#if defined(__APPLE__)
// In Mac OS X 10.4, CrashReporter will write a crash log for all 'fatal' signals, including
// signals caught and handled by the JVM. To work around this, we reset the mach task
// signal handler that's placed on our process by CrashReporter. This disables
// CrashReporter-based reporting.
//
// This work-around is not necessary for 10.5+, as CrashReporter no longer intercedes
// on caught fatal signals.
//
// Additionally, gdb installs both standard BSD signal handlers, and mach exception
// handlers. By replacing the existing task exception handler, we disable gdb's mach
// exception handling, while leaving the standard BSD signal handlers functional.
kern_return_t kr;
kr = task_set_exception_ports(mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC,
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
// In Mac OS X 10.4, CrashReporter will write a crash log for all 'fatal' signals, including
// signals caught and handled by the JVM. To work around this, we reset the mach task
// signal handler that's placed on our process by CrashReporter. This disables
// CrashReporter-based reporting.
//
// This work-around is not necessary for 10.5+, as CrashReporter no longer intercedes
// on caught fatal signals.
//
// Additionally, gdb installs both standard BSD signal handlers, and mach exception
// handlers. By replacing the existing task exception handler, we disable gdb's mach
// exception handling, while leaving the standard BSD signal handlers functional.
kern_return_t kr;
kr = task_set_exception_ports(mach_task_self(),
EXC_MASK_BAD_ACCESS | EXC_MASK_ARITHMETIC,
MACH_PORT_NULL,
EXCEPTION_STATE_IDENTITY,
MACHINE_THREAD_STATE);
assert(kr == KERN_SUCCESS, "could not set mach task signal handler");
assert(kr == KERN_SUCCESS, "could not set mach task signal handler");
#endif
if (libjsig_is_loaded) {
// Tell libjsig jvm finishes setting signal handlers
(*end_signal_setting)();
}
if (libjsig_is_loaded) {
// Tell libjsig jvm finishes setting signal handlers
(*end_signal_setting)();
}
// We don't activate signal checker if libjsig is in place, we trust ourselves
// and if UserSignalHandler is installed all bets are off.
// Log that signal checking is off only if -verbose:jni is specified.
if (CheckJNICalls) {
if (libjsig_is_loaded) {
log_debug(jni, resolve)("Info: libjsig is activated, all active signal checking is disabled");
check_signals = false;
}
if (AllowUserSignalHandlers) {
log_debug(jni, resolve)("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled");
check_signals = false;
}
// We don't activate signal checker if libjsig is in place, we trust ourselves
// and if UserSignalHandler is installed all bets are off.
// Log that signal checking is off only if -verbose:jni is specified.
if (CheckJNICalls) {
if (libjsig_is_loaded) {
log_debug(jni, resolve)("Info: libjsig is activated, all active signal checking is disabled");
check_signals = false;
}
if (AllowUserSignalHandlers) {
log_debug(jni, resolve)("Info: AllowUserSignalHandlers is activated, all active signal checking is disabled");
check_signals = false;
}
}
}
@ -1354,9 +1421,7 @@ void PosixSignals::signal_sets_init() {
sigaddset(&unblocked_sigs, SIGSEGV);
sigaddset(&unblocked_sigs, SIGBUS);
sigaddset(&unblocked_sigs, SIGFPE);
#if defined(PPC64) || defined(AIX)
sigaddset(&unblocked_sigs, SIGTRAP);
#endif
PPC64_ONLY(sigaddset(&unblocked_sigs, SIGTRAP);)
sigaddset(&unblocked_sigs, SR_signum);
if (!ReduceSignalUsage) {

View File

@ -38,7 +38,11 @@ class PosixSignals : public AllStatic {
public:
static bool are_signal_handlers_installed();
// The platform dependent parts of the central hotspot signal handler.
// Returns true if the signal had been recognized and handled, false if not. If true, caller should
// return from signal handling.
static bool pd_hotspot_signal_handler(int sig, siginfo_t* info, ucontext_t* uc, JavaThread* thread);
static void install_signal_handlers();
static bool is_sig_ignored(int sig);

View File

@ -2144,6 +2144,8 @@ static int check_pending_signals() {
}
} while (threadIsSuspended);
}
ShouldNotReachHere();
return 0; // Satisfy compiler
}
int os::signal_wait() {

View File

@ -168,43 +168,8 @@ frame os::current_frame() {
return os::get_sender_for_C_frame(&tmp);
}
// Utility functions
extern "C" JNIEXPORT int
JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
Thread* t = Thread::current_or_null_safe();
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_aix_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return 1;
} else {
// Ignoring SIGPIPE - see bugs 4229104
return 1;
}
}
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()) {
vmthread = (VMThread *)t;
}
}
}
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
// Decide if this trap can be handled by a stub.
address stub = NULL;
@ -226,8 +191,8 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
}
}
if (info == NULL || uc == NULL || thread == NULL && vmthread == NULL) {
goto run_chained_handler;
if (info == NULL || uc == NULL) {
return false; // Fatal error
}
// If we are a java thread...
@ -237,11 +202,11 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
if (sig == SIGSEGV && thread->is_in_full_stack(addr)) {
// stack overflow
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
return 1; // continue
return true; // continue
} else if (stub != NULL) {
goto run_stub;
} else {
goto report_and_die;
return false; // Fatal error
}
} // end handle SIGSEGV inside stack boundaries
@ -281,17 +246,6 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
// happens rarely. In heap based and disjoint base compressd oop modes also loads
// are used for null checks.
// A VM-related SIGILL may only occur if we are not in the zero page.
// On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else
// in the zero page, because it is filled with 0x0. We ignore
// explicit SIGILLs in the zero page.
if (sig == SIGILL && (pc < (address) 0x200)) {
if (TraceTraps) {
tty->print_raw_cr("SIGILL happened inside zero page.");
}
goto report_and_die;
}
int stop_type = -1;
// Handle signal from NativeJump::patch_verified_entry().
if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_zombie_not_entrant()) {
@ -384,10 +338,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
tty->print_cr("trap: %s: %s (SIGTRAP, stop type %d)", msg, detail_msg, stop_type);
}
va_list detail_args;
VMError::report_and_die(INTERNAL_ERROR, msg, detail_msg, detail_args, thread,
pc, info, ucVoid, NULL, 0, 0);
va_end(detail_args);
return false; // Fatal error
}
else if (sig == SIGBUS) {
@ -403,7 +354,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
}
next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
os::Aix::ucontext_set_pc(uc, next_pc);
return 1;
return true;
}
}
}
@ -428,7 +379,7 @@ JVM_handle_aix_signal(int sig, siginfo_t* info, void* ucVoid, int abort_if_unrec
}
next_pc = SharedRuntime::handle_unsafe_access(thread, next_pc);
os::Aix::ucontext_set_pc(uc, next_pc);
return 1;
return true;
}
}
@ -450,32 +401,10 @@ run_stub:
// Save all thread context in case we need to restore it.
if (thread != NULL) thread->set_saved_exception_pc(pc);
os::Aix::ucontext_set_pc(uc, stub);
return 1;
return true;
}
run_chained_handler:
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return 1;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return 0;
}
report_and_die:
// Use sigthreadmask instead of sigprocmask on AIX and unmask current signal.
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigthreadmask(SIG_UNBLOCK, &newset, NULL);
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return 0;
return false; // Fatal error
}
void os::Aix::init_thread_fpu_state(void) {

View File

@ -385,56 +385,14 @@ frame os::current_frame() {
}
}
// Utility functions
// From IA32 System Programming Guide
enum {
trap_page_fault = 0xE
};
extern "C" JNIEXPORT int
JVM_handle_bsd_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
Thread* t = Thread::current_or_null_safe();
// If crash protection is installed we may longjmp away and no destructors
// for objects in this scope will be run.
// So don't use any RAII utilities before crash protection is checked.
os::ThreadCrashProtection::check_crash_protection(sig, t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_bsd_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
return true;
}
}
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()){
vmthread = (VMThread *)t;
}
}
}
/*
NOTE: does not seem to work on bsd.
if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
@ -455,7 +413,7 @@ JVM_handle_bsd_signal(int sig,
if (StubRoutines::is_safefetch_fault(pc)) {
os::Bsd::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
return true;
}
// Handle ALL stack overflow variations here
@ -466,7 +424,7 @@ JVM_handle_bsd_signal(int sig,
if (thread->is_in_full_stack(addr)) {
// stack overflow
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
return 1; // continue
return true; // continue
}
}
}
@ -678,29 +636,6 @@ JVM_handle_bsd_signal(int sig,
return true;
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
if (pc == NULL && uc != NULL) {
pc = os::Bsd::ucontext_get_pc(uc);
}
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL);
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return false;
}

View File

@ -115,16 +115,10 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
return frame();
}
extern "C" JNIEXPORT int
JVM_handle_bsd_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
Thread* t = Thread::current_or_null_safe();
// handle SafeFetch faults
// handle SafeFetch faults the zero way
if (sig == SIGSEGV || sig == SIGBUS) {
sigjmp_buf* const pjb = get_jmp_buf_for_continuation();
if (pjb) {
@ -132,37 +126,6 @@ JVM_handle_bsd_signal(int sig,
}
}
// Note: it's not uncommon that JNI code uses signal/sigset to
// install then restore certain signal handler (e.g. to temporarily
// block SIGPIPE, or have a SIGILL handler when detecting CPU
// type). When that happens, JVM_handle_bsd_signal() might be
// invoked with junk info/ucVoid. To avoid unnecessary crash when
// libjsig is not preloaded, try handle signals that do not require
// siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
return true;
}
}
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()){
vmthread = (VMThread *)t;
}
}
}
if (info != NULL && thread != NULL) {
// Handle ALL stack overflow variations here
if (sig == SIGSEGV || sig == SIGBUS) {
@ -202,36 +165,6 @@ JVM_handle_bsd_signal(int sig,
}*/
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
#ifndef PRODUCT
if (sig == SIGSEGV) {
fatal("\n#"
"\n# /--------------------\\"
"\n# | segmentation fault |"
"\n# \\---\\ /--------------/"
"\n# /"
"\n# [-] |\\_/| "
"\n# (+)=C |o o|__ "
"\n# | | =-*-=__\\ "
"\n# OOO c_c_(___)");
}
#endif // !PRODUCT
const char *fmt =
"caught unhandled signal " INT32_FORMAT " at address " PTR_FORMAT;
char buf[128];
sprintf(buf, fmt, sig, info->si_addr);
fatal(buf);
return false;
}

View File

@ -164,57 +164,9 @@ NOINLINE frame os::current_frame() {
}
}
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
Thread* t = Thread::current_or_null_safe();
// If crash protection is installed we may longjmp away and no destructors
// for objects in this scope will be run.
// So don't use any RAII utilities before crash protection is checked.
os::ThreadCrashProtection::check_crash_protection(sig, t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
return true;
}
}
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
return 1;
}
}
#endif
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()){
vmthread = (VMThread *)t;
}
}
}
/*
NOTE: does not seem to work on linux.
if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
@ -235,7 +187,7 @@ JVM_handle_linux_signal(int sig,
if (StubRoutines::is_safefetch_fault(pc)) {
os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
return true;
}
address addr = (address) info->si_addr;
@ -250,7 +202,7 @@ JVM_handle_linux_signal(int sig,
// check if fault address is within thread stack
if (thread->is_in_full_stack(addr)) {
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
return 1; // continue
return true; // continue
}
}
}
@ -293,10 +245,7 @@ JVM_handle_linux_signal(int sig,
tty->print_cr("trap: %s: (SIGILL)", msg);
}
va_list detail_args;
VMError::report_and_die(INTERNAL_ERROR, msg, detail_msg, detail_args, thread,
pc, info, ucVoid, NULL, 0, 0);
va_end(detail_args);
return false; // Fatal error
}
else
@ -342,30 +291,8 @@ JVM_handle_linux_signal(int sig,
return true;
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
return false; // Mute compiler
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
if (pc == NULL && uc != NULL) {
pc = os::Linux::ucontext_get_pc(uc);
}
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL);
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return true; // Mute compiler
}
void os::Linux::init_thread_fpu_state(void) {

View File

@ -241,18 +241,9 @@ address check_vfp3_32_fault_instr = NULL;
address check_simd_fault_instr = NULL;
address check_mp_ext_fault_instr = NULL;
// Utility functions
extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
void* ucVoid, int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
Thread* t = Thread::current_or_null_safe();
// If crash protection is installed we may longjmp away and no destructors
// for objects in this scope will be run.
// So don't use any RAII utilities before crash protection is checked.
os::ThreadCrashProtection::check_crash_protection(sig, t);
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
if (sig == SIGILL &&
((info->si_addr == (caddr_t)check_simd_fault_instr)
@ -266,44 +257,6 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
return true;
}
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
return true;
}
}
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
return 1;
}
}
#endif
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()){
vmthread = (VMThread *)t;
}
}
}
address stub = NULL;
address pc = NULL;
bool unsafe_access = false;
@ -317,7 +270,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
if (StubRoutines::is_safefetch_fault(pc)) {
os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
return true;
}
// check if fault address is within thread stack
if (thread->is_in_full_stack(addr)) {
@ -331,7 +284,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
stub = SharedRuntime::continuation_for_implicit_exception(thread, pc, SharedRuntime::STACK_OVERFLOW);
} else {
// Thread was in the vm or native code. Return and try to finish.
return 1;
return true;
}
} else if (overflow_state->in_stack_red_zone(addr)) {
// Fatal red zone violation. Disable the guard pages and fall through
@ -347,7 +300,7 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
thread->osthread()->set_expanding_stack();
if (os::Linux::manually_expand_stack(thread, addr)) {
thread->osthread()->clear_expanding_stack();
return 1;
return true;
}
thread->osthread()->clear_expanding_stack();
} else {
@ -440,30 +393,8 @@ extern "C" int JVM_handle_linux_signal(int sig, siginfo_t* info,
return true;
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
if (pc == NULL && uc != NULL) {
pc = os::Linux::ucontext_get_pc(uc);
}
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL);
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return false;
}
void os::Linux::init_thread_fpu_state(void) {

View File

@ -188,32 +188,8 @@ frame os::current_frame() {
return os::get_sender_for_C_frame(&tmp);
}
// Utility functions
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
Thread* t = Thread::current_or_null_safe();
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE - see bugs 4229104
return true;
}
}
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
// Make the signal handler transaction-aware by checking the existence of a
// second (transactional) context with MSR TS bits active. If the signal is
@ -237,26 +213,6 @@ JVM_handle_linux_signal(int sig,
}
}
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
return 1;
}
}
#endif
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
} else if(t->is_VM_thread()) {
vmthread = (VMThread *)t;
}
}
}
// Moved SafeFetch32 handling outside thread!=NULL conditional block to make
// it work if no associated JavaThread object exists.
if (uc) {
@ -297,7 +253,7 @@ JVM_handle_linux_signal(int sig,
if (thread->is_in_full_stack(addr)) {
// stack overflow
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
return 1; // continue
return true; // continue
}
}
}
@ -306,17 +262,6 @@ JVM_handle_linux_signal(int sig,
// Java thread running in Java code => find exception handler if any
// a fault inside compiled code, the interpreter, or a stub
// A VM-related SIGILL may only occur if we are not in the zero page.
// On AIX, we get a SIGILL if we jump to 0x0 or to somewhere else
// in the zero page, because it is filled with 0x0. We ignore
// explicit SIGILLs in the zero page.
if (sig == SIGILL && (pc < (address) 0x200)) {
if (TraceTraps) {
tty->print_raw_cr("SIGILL happened inside zero page.");
}
goto report_and_die;
}
CodeBlob *cb = NULL;
int stop_type = -1;
// Handle signal from NativeJump::patch_verified_entry().
@ -404,10 +349,7 @@ JVM_handle_linux_signal(int sig,
tty->print_cr("trap: %s: %s (SIGTRAP, stop type %d)", msg, detail_msg, stop_type);
}
va_list detail_args;
VMError::report_and_die(INTERNAL_ERROR, msg, detail_msg, detail_args, thread,
pc, info, ucVoid, NULL, 0, 0);
va_end(detail_args);
return false; // Fatal error
}
else if (sig == SIGBUS) {
@ -465,31 +407,8 @@ JVM_handle_linux_signal(int sig,
return true;
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
if (pc == NULL && uc != NULL) {
pc = os::Linux::ucontext_get_pc(uc);
}
report_and_die:
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL);
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return false;
}
void os::Linux::init_thread_fpu_state(void) {

View File

@ -204,59 +204,8 @@ frame os::current_frame() {
}
}
// Utility functions
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
Thread* t = Thread::current_or_null_safe();
// If crash protection is installed we may longjmp away and no destructors
// for objects in this scope will be run.
// So don't use any RAII utilities before crash protection is checked.
os::ThreadCrashProtection::check_crash_protection(sig, t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
if (PrintMiscellaneous && (WizardMode || Verbose)) {
warning("Ignoring SIGPIPE - see bug 4229104");
}
return true;
}
}
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
return 1;
}
}
#endif
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL) {
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
} else if(t->is_VM_thread()) {
vmthread = (VMThread *)t;
}
}
}
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
// Moved SafeFetch32 handling outside thread!=NULL conditional block to make
// it work if no associated JavaThread object exists.
@ -294,7 +243,7 @@ JVM_handle_linux_signal(int sig,
if (thread->is_in_full_stack(addr)) {
// stack overflow
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
return 1; // continue
return true; // continue
}
}
}
@ -418,38 +367,8 @@ JVM_handle_linux_signal(int sig,
return true;
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
if (pc == NULL && uc != NULL) {
pc = os::Linux::ucontext_get_pc(uc);
}
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL);
// Hand down correct pc for SIGILL, SIGFPE. pc from context
// usually points to the instruction after the failing instruction.
// Note: this should be combined with the trap_pc handling above,
// because it handles the same issue.
if (sig == SIGILL || sig == SIGFPE) {
pc = (address)info->si_addr;
}
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return false;
}
void os::Linux::init_thread_fpu_state(void) {

View File

@ -200,58 +200,10 @@ enum {
trap_page_fault = 0xE
};
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
Thread* t = Thread::current_or_null_safe();
// If crash protection is installed we may longjmp away and no destructors
// for objects in this scope will be run.
// So don't use any RAII utilities before crash protection is checked.
os::ThreadCrashProtection::check_crash_protection(sig, t);
// Note: it's not uncommon that JNI code uses signal/sigset to install
// then restore certain signal handler (e.g. to temporarily block SIGPIPE,
// or have a SIGILL handler when detecting CPU type). When that happens,
// JVM_handle_linux_signal() might be invoked with junk info/ucVoid. To
// avoid unnecessary crash when libjsig is not preloaded, try handle signals
// that do not require siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
return true;
}
}
#ifdef CAN_SHOW_REGISTERS_ON_ASSERT
if ((sig == SIGSEGV || sig == SIGBUS) && info != NULL && info->si_addr == g_assert_poison) {
if (handle_assert_poison_fault(ucVoid, info->si_addr)) {
return 1;
}
}
#endif
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()){
vmthread = (VMThread *)t;
}
}
}
/*
/*
NOTE: does not seem to work on linux.
if (info == NULL || info->si_code <= 0 || info->si_code == SI_NOINFO) {
// can't decode this kind of signal
@ -271,7 +223,7 @@ JVM_handle_linux_signal(int sig,
if (StubRoutines::is_safefetch_fault(pc)) {
os::Linux::ucontext_set_pc(uc, StubRoutines::continuation_for_safefetch_fault(pc));
return 1;
return true;
}
#ifndef AMD64
@ -292,7 +244,7 @@ JVM_handle_linux_signal(int sig,
if (thread->is_in_full_stack(addr)) {
// stack overflow
if (os::Posix::handle_stack_overflow(thread, addr, pc, uc, &stub)) {
return 1; // continue
return true; // continue
}
}
}
@ -469,30 +421,7 @@ JVM_handle_linux_signal(int sig,
return true;
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
if (pc == NULL && uc != NULL) {
pc = os::Linux::ucontext_get_pc(uc);
}
// unmask current signal
sigset_t newset;
sigemptyset(&newset);
sigaddset(&newset, sig);
sigprocmask(SIG_UNBLOCK, &newset, NULL);
VMError::report_and_die(t, sig, pc, info, ucVoid);
ShouldNotReachHere();
return true; // Mute compiler
return false;
}
void os::Linux::init_thread_fpu_state(void) {

View File

@ -111,14 +111,8 @@ frame os::fetch_frame_from_context(const void* ucVoid) {
return frame(NULL, NULL); // silence compile warnings
}
extern "C" JNIEXPORT int
JVM_handle_linux_signal(int sig,
siginfo_t* info,
void* ucVoid,
int abort_if_unrecognized) {
ucontext_t* uc = (ucontext_t*) ucVoid;
Thread* t = Thread::current_or_null_safe();
bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
ucontext_t* uc, JavaThread* thread) {
// handle SafeFetch faults
if (sig == SIGSEGV || sig == SIGBUS) {
@ -128,37 +122,6 @@ JVM_handle_linux_signal(int sig,
}
}
// Note: it's not uncommon that JNI code uses signal/sigset to
// install then restore certain signal handler (e.g. to temporarily
// block SIGPIPE, or have a SIGILL handler when detecting CPU
// type). When that happens, JVM_handle_linux_signal() might be
// invoked with junk info/ucVoid. To avoid unnecessary crash when
// libjsig is not preloaded, try handle signals that do not require
// siginfo/ucontext first.
if (sig == SIGPIPE || sig == SIGXFSZ) {
// allow chained handler to go first
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
} else {
// Ignoring SIGPIPE/SIGXFSZ - see bugs 4229104 or 6499219
return true;
}
}
JavaThread* thread = NULL;
VMThread* vmthread = NULL;
if (PosixSignals::are_signal_handlers_installed()) {
if (t != NULL ){
if(t->is_Java_thread()) {
thread = t->as_Java_thread();
}
else if(t->is_VM_thread()){
vmthread = (VMThread *)t;
}
}
}
if (info != NULL && thread != NULL) {
// Handle ALL stack overflow variations here
if (sig == SIGSEGV) {
@ -216,47 +179,8 @@ JVM_handle_linux_signal(int sig,
}*/
}
// signal-chaining
if (PosixSignals::chained_handler(sig, info, ucVoid)) {
return true;
}
return false; // Fatal error
if (!abort_if_unrecognized) {
// caller wants another chance, so give it to him
return false;
}
#ifndef PRODUCT
if (sig == SIGSEGV) {
fatal("\n#"
"\n# /--------------------\\"
"\n# | segmentation fault |"
"\n# \\---\\ /--------------/"
"\n# /"
"\n# [-] |\\_/| "
"\n# (+)=C |o o|__ "
"\n# | | =-*-=__\\ "
"\n# OOO c_c_(___)");
}
#endif // !PRODUCT
char buf[128];
char exc_buf[32];
if (os::exception_name(sig, exc_buf, sizeof(exc_buf))) {
bool sent_by_kill = (info != NULL && os::signal_sent_by_kill(info));
snprintf(buf, sizeof(buf), "caught unhandled signal: %s %s",
exc_buf, sent_by_kill ? "(sent by kill)" : "");
} else {
snprintf(buf, sizeof(buf), "caught unhandled signal: %d", sig);
}
// Silence -Wformat-security warning for fatal()
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_NONLITERAL_IGNORED
fatal(buf);
PRAGMA_DIAG_POP
return true; // silence compiler warnings
}
void os::Linux::init_thread_fpu_state(void) {

View File

@ -755,7 +755,7 @@ const intx ObjectAlignmentInBytes = 8;
"tables") \
\
product(bool, AllowUserSignalHandlers, false, \
"Do not complain if the application installs signal handlers " \
"Application will install primary signal handlers for the JVM " \
"(Unix only)") \
\
product(bool, UseSignalChaining, true, \

View File

@ -116,9 +116,6 @@ class VMError : public AllStatic {
// and the offending address points into CDS store.
static void check_failing_cds_access(outputStream* st, const void* siginfo);
static void report_and_die(Thread* thread, unsigned int sig, address pc, void* siginfo,
void* context, const char* detail_fmt, ...) ATTRIBUTE_PRINTF(6, 7);
// Timeout handling.
// Hook functions for platform dependend functionality:
static void reporting_started();
@ -146,6 +143,9 @@ public:
static void print_vm_info(outputStream* st);
// main error reporting function
static void report_and_die(Thread* thread, unsigned int sig, address pc, void* siginfo,
void* context, const char* detail_fmt, ...) ATTRIBUTE_PRINTF(6, 7);
static void report_and_die(int id, const char* message, const char* detail_fmt, va_list detail_args,
Thread* thread, address pc, void* siginfo, void* context,
const char* filename, int lineno, size_t size) ATTRIBUTE_PRINTF(3, 0);