diff --git a/vm/port/src/crash_handler/include/stack_dump.h b/vm/port/src/crash_handler/include/stack_dump.h index 20816e6..5b5d39a 100644 --- a/vm/port/src/crash_handler/include/stack_dump.h +++ b/vm/port/src/crash_handler/include/stack_dump.h @@ -65,6 +65,10 @@ int port_process_signal(port_sigtype signum, Registers *regs, void* fault_addr, void create_minidump(LPEXCEPTION_POINTERS exp); #endif + +Boolean sd_is_handler_registered(port_sigtype signum); + + #ifdef __cplusplus } #endif diff --git a/vm/port/src/crash_handler/port_crash_handler.cpp b/vm/port/src/crash_handler/port_crash_handler.cpp index 9431b0c..5bbc0ff 100644 --- a/vm/port/src/crash_handler/port_crash_handler.cpp +++ b/vm/port/src/crash_handler/port_crash_handler.cpp @@ -23,7 +23,7 @@ #include "signals_internal.h" #include "port_crash_handler.h" -static port_signal_handler signal_callbacks[] = +port_signal_handler signal_callbacks[] = { NULL, // PORT_SIGNAL_GPF NULL, // PORT_SIGNAL_STACK_OVERFLOW @@ -55,16 +55,12 @@ Boolean port_init_crash_handler( unsigned count, port_unwind_compiled_frame unwind_callback) { - if (initialize_signals() != 0) + if (port_mutex_create(&g_mutex, APR_THREAD_MUTEX_NESTED) != APR_SUCCESS) return FALSE; if (init_private_tls_data() != 0) return FALSE; - port_mutex_create(&g_mutex, APR_THREAD_MUTEX_NESTED); - - sd_init_crash_handler(); - for (unsigned iii = 0; iii < count; iii++) { assert(registrations[iii].signum >= PORT_SIGNAL_MIN); @@ -72,6 +68,12 @@ Boolean port_init_crash_handler( signal_callbacks[registrations[iii].signum] = registrations[iii].callback; } + // initialize_signals needs to know what handlers are registered + if (initialize_signals() != 0) + return FALSE; + + sd_init_crash_handler(); + g_unwind_callback = unwind_callback; // Set default flags @@ -158,12 +160,14 @@ int port_process_signal(port_sigtype signum, Registers *regs, void* fault_addr, { if (!iscrash) { - assert(signum >= PORT_SIGNAL_MIN); - assert(signum <= PORT_SIGNAL_MAX); + if (signum < PORT_SIGNAL_MIN || + signum > PORT_SIGNAL_MAX) + return 0; if (signal_callbacks[signum] != NULL) { - Boolean cres = signal_callbacks[signum](signum, regs, fault_addr); + Boolean cres = + signal_callbacks[signum](signum, regs, fault_addr); if (cres) // signal was processed return 0; @@ -189,3 +193,8 @@ int port_process_signal(port_sigtype signum, Registers *regs, void* fault_addr, return -1; } + +Boolean sd_is_handler_registered(port_sigtype signum) +{ + return signal_callbacks[signum] != NULL; +} diff --git a/vm/port/src/signals/linux/signals_common.cpp b/vm/port/src/signals/linux/signals_common.cpp index 999a871..3e59778 100644 --- a/vm/port/src/signals/linux/signals_common.cpp +++ b/vm/port/src/signals/linux/signals_common.cpp @@ -187,18 +187,19 @@ static void general_signal_handler(int signum, siginfo_t* info, void* context) struct sig_reg { int signal; + port_sigtype port_sig; int flags; bool set_up; }; static sig_reg signals_used[] = { - { SIGTRAP, SA_SIGINFO, false }, - { SIGSEGV, SA_SIGINFO | SA_ONSTACK, false }, - { SIGFPE, SA_SIGINFO, false }, - { SIGINT, SA_SIGINFO, false }, - { SIGQUIT, SA_SIGINFO, false }, - { SIGABRT, SA_SIGINFO, false } + { SIGTRAP, PORT_SIGNAL_BREAKPOINT, SA_SIGINFO, false }, + { SIGSEGV, PORT_SIGNAL_GPF, SA_SIGINFO | SA_ONSTACK, false }, + { SIGFPE, PORT_SIGNAL_ARITHMETIC, SA_SIGINFO, false }, + { SIGINT, PORT_SIGNAL_CTRL_C, SA_SIGINFO, false }, + { SIGQUIT, PORT_SIGNAL_QUIT, SA_SIGINFO, false }, + { SIGABRT, PORT_SIGNAL_ABORT, SA_SIGINFO, false } }; static struct sigaction old_actions[sizeof(signals_used)/sizeof(signals_used[0])]; @@ -222,6 +223,9 @@ int initialize_signals() for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++) { + if (!sd_is_handler_registered(signals_used[i].port_sig)) + continue; + sigemptyset(&sa.sa_mask); sa.sa_flags = signals_used[i].flags; sa.sa_sigaction = &general_signal_handler; @@ -231,6 +235,8 @@ int initialize_signals() restore_signals(); return -1; } + + signals_used[i].set_up = true; } // Prepare gdb crash handler diff --git a/vm/port/src/signals/linux/signals_ipf.cpp b/vm/port/src/signals/linux/signals_ipf.cpp index 69cbcac..4ee4944 100644 --- a/vm/port/src/signals/linux/signals_ipf.cpp +++ b/vm/port/src/signals/linux/signals_ipf.cpp @@ -118,18 +118,19 @@ static void general_signal_handler(int signum, siginfo_t* info, void* context) struct sig_reg { int signal; + port_sigtype port_sig; int flags; bool set_up; }; static sig_reg signals_used[] = { - { SIGTRAP, SA_SIGINFO, false }, - { SIGSEGV, SA_SIGINFO | SA_ONSTACK, false }, - { SIGFPE, SA_SIGINFO, false }, - { SIGINT, SA_SIGINFO, false }, - { SIGQUIT, SA_SIGINFO, false }, - { SIGABRT, SA_SIGINFO, false } + { SIGTRAP, PORT_SIGNAL_BREAKPOINT, SA_SIGINFO, false }, + { SIGSEGV, PORT_SIGNAL_GPF, SA_SIGINFO | SA_ONSTACK, false }, + { SIGFPE, PORT_SIGNAL_ARITHMETIC, SA_SIGINFO, false }, + { SIGINT, PORT_SIGNAL_CTRL_C, SA_SIGINFO, false }, + { SIGQUIT, PORT_SIGNAL_QUIT, SA_SIGINFO, false }, + { SIGABRT, PORT_SIGNAL_ABORT, SA_SIGINFO, false } }; static struct sigaction old_actions[sizeof(signals_used)/sizeof(signals_used[0])]; @@ -153,6 +154,9 @@ int initialize_signals() for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++) { + if (!sd_is_handler_registered(signals_used[i].port_sig)) + continue; + sigemptyset(&sa.sa_mask); sa.sa_flags = signals_used[i].flags; sa.sa_sigaction = &general_signal_handler; @@ -162,6 +166,8 @@ int initialize_signals() restore_signals(); return -1; } + + signals_used[i].set_up = true; } // Prepare gdb crash handler diff --git a/vm/port/src/signals/win/signals_common.cpp b/vm/port/src/signals/win/signals_common.cpp index 8a5ab26..c777df8 100644 --- a/vm/port/src/signals/win/signals_common.cpp +++ b/vm/port/src/signals/win/signals_common.cpp @@ -164,13 +164,24 @@ LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception switch (nt_exception->ExceptionRecord->ExceptionCode) { case STATUS_STACK_OVERFLOW: + if (!sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW)) + return EXCEPTION_CONTINUE_SEARCH; + break; case STATUS_ACCESS_VIOLATION: + if (!sd_is_handler_registered(PORT_SIGNAL_GPF)) + return EXCEPTION_CONTINUE_SEARCH; + break; case JVMTI_EXCEPTION_STATUS: + if (!sd_is_handler_registered(PORT_SIGNAL_BREAKPOINT)) + return EXCEPTION_CONTINUE_SEARCH; + break; case STATUS_INTEGER_DIVIDE_BY_ZERO: case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_UNDERFLOW: case EXCEPTION_INT_OVERFLOW: + if (!sd_is_handler_registered(PORT_SIGNAL_ARITHMETIC)) + return EXCEPTION_CONTINUE_SEARCH; break; default: return EXCEPTION_CONTINUE_SEARCH; @@ -194,6 +205,9 @@ BOOL ctrl_handler(DWORD ctrlType) switch (ctrlType) { case CTRL_BREAK_EVENT: + if (!sd_is_handler_registered(PORT_SIGNAL_CTRL_BREAK)) + return FALSE; + result = port_process_signal(PORT_SIGNAL_CTRL_BREAK, NULL, NULL, FALSE); if (result == 0) return TRUE; @@ -204,6 +218,9 @@ BOOL ctrl_handler(DWORD ctrlType) case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: + if (!sd_is_handler_registered(PORT_SIGNAL_CTRL_C)) + return FALSE; + result = port_process_signal(PORT_SIGNAL_CTRL_C, NULL, NULL, FALSE); if (result == 0) return TRUE;