BOOL ctrl_handler(DWORD ctrlType) { int result = 0; 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; else return FALSE; case CTRL_C_EVENT: 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; else return FALSE; } return FALSE; }
int initialize_signals() { struct sigaction sa; for (size_t i = 0; i < sizeof(signals_used)/sizeof(signals_used[0]); i++) { if (!sd_is_handler_registered(signals_used[i].port_sig) && signals_used[i].signal != SIGSEGV) // Sigsegv is needed for port_memaccess continue; sigemptyset(&sa.sa_mask); sa.sa_flags = signals_used[i].flags; sa.sa_sigaction = &general_signal_handler; if (0 != sigaction(signals_used[i].signal, &sa, &old_actions[i])) { restore_signals(); return -1; } signals_used[i].set_up = true; } for (size_t j = 0; j < sizeof(signals_other)/sizeof(signals_other[0]); j++) { old_handlers[j] = signal(signals_other[j].signal, signals_other[j].handler); if (old_handlers[j] == SIG_ERR) { restore_signals(); return -1; } signals_other[j].set_up = true; } // Prepare gdb crash handler if (!init_gdb_crash_handler()) { restore_signals(); return -1; } return 0; } //initialize_signals
LONG NTAPI vectored_exception_handler_internal(LPEXCEPTION_POINTERS nt_exception) { DWORD code = nt_exception->ExceptionRecord->ExceptionCode; void* fault_addr = nt_exception->ExceptionRecord->ExceptionAddress; Registers regs; // Convert NT context to Registers port_thread_context_to_regs(®s, nt_exception->ContextRecord); // Check if TLS structure is set - probably we should produce minidump port_tls_data_t* tlsdata = get_private_tls_data(); if (!tlsdata) // Tread is not attached - attach thread temporarily { int res; tlsdata = (port_tls_data_t*)STD_MALLOC(sizeof(port_tls_data_t)); if (tlsdata) // Try to attach the thread res = port_thread_attach_local(tlsdata, TRUE, TRUE, 0); if (!tlsdata || res != 0) { // Can't process correctly; perform default actions if (FLAG_CORE) create_minidump(nt_exception); if (FLAG_DBG) { show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work _exit(-1); return EXCEPTION_CONTINUE_SEARCH; // Assert dialog } _exit(-1); } // SO for alien thread can't be processed out of VEH if (code == STATUS_STACK_OVERFLOW && sd_is_handler_registered(PORT_SIGNAL_STACK_OVERFLOW)) { int result; size_t alt_stack_size = ALT_PAGES_COUNT*tlsdata->guard_page_size; void* alt_stack = map_alt_stack(alt_stack_size); void* stack_bottom = (void*)((POINTER_SIZE_INT)alt_stack + alt_stack_size); if (alt_stack) result = (int)(POINTER_SIZE_INT)port_call_alt_stack( port_process_signal, stack_bottom, 4, PORT_SIGNAL_STACK_OVERFLOW, ®s, fault_addr, FALSE); else result = port_process_signal(PORT_SIGNAL_STACK_OVERFLOW, ®s, fault_addr, FALSE); if (result == 0) { if (port_thread_detach_temporary() == 0) STD_FREE(tlsdata); if (alt_stack) unmap_alt_stack(alt_stack, alt_stack_size); return EXCEPTION_CONTINUE_EXECUTION; } if (FLAG_CORE) { if (alt_stack) port_call_alt_stack(create_minidump, stack_bottom, 1, nt_exception); else create_minidump(nt_exception); } if (alt_stack) unmap_alt_stack(alt_stack, alt_stack_size); if (result > 0) { show_debugger_dialog(); // Workaround; EXCEPTION_CONTINUE_SEARCH does not work _exit(-1); shutdown_signals(); return EXCEPTION_CONTINUE_SEARCH; // Assert dialog } _exit(-1); } } if (tlsdata->produce_core) { create_minidump(nt_exception); if (!tlsdata->debugger) _exit(-1); } if (tlsdata->debugger) { show_debugger_dialog(); // Workaround _exit(-1); // Go to handler to restore CRT/VEH settings and crash once again // port_set_longjump_regs(&prepare_assert_dialog, ®s, 1, ®s); // port_thread_regs_to_context(nt_exception->ContextRecord, ®s); // return EXCEPTION_CONTINUE_EXECUTION; } switch (code) { 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; } if (code == STATUS_STACK_OVERFLOW) { tlsdata->guard_page_set = FALSE; // GUARD_PAGE was cleared by OS if (!tlsdata->restore_guard_page) tlsdata->restore_guard_page = TRUE; } // Prepare to transfering control out of VEH handler port_set_longjump_regs(&c_handler, ®s, 4, ®s, nt_exception->ExceptionRecord->ExceptionAddress, (void*)(size_t)nt_exception->ExceptionRecord->ExceptionCode, (void*)(size_t)nt_exception->ExceptionRecord->ExceptionFlags); // Convert prepared Registers back to NT context port_thread_regs_to_context(nt_exception->ContextRecord, ®s); // Return from VEH - presumably continue execution return EXCEPTION_CONTINUE_EXECUTION; }