From 7805eb0cc29e1762d9c0bb207f5f9a910f292bf7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 27 Sep 2008 14:08:13 +0000 Subject: [PATCH] Changed the handling for hardware-caused terminal signals: * No longer send a SIGKILL when a page fault occurred, there was no signal handler, and the debugger told us to continue as usual. Instead we send a SIGSEGV. Instead in handle_signal() when not in the main thread and there's no handler for the signal, we first send the main thread a SIGKILL before letting the thread die. So in cases where the main thread caused an unhandled page fault, the team will die from the SIGSEGV, now. This fixes bug #2773. * For the other hardware-caused signals we do now do the same as in case of page faults, i.e. we first check whether the thread has a handler for the signal in question. If so, we don't notify the debugger, but send the signal right away. * B_GENERAL_PROTECTION_FAULT is translated to SIGILL now. Seems better than SIGKILL. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27757 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/arch/x86/arch_int.c | 13 +++++++++++-- src/system/kernel/signal.cpp | 12 +++++++++--- src/system/kernel/vm/vm.cpp | 8 ++++---- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/system/kernel/arch/x86/arch_int.c b/src/system/kernel/arch/x86/arch_int.c index ef14c5c73f..69e3475c57 100644 --- a/src/system/kernel/arch/x86/arch_int.c +++ b/src/system/kernel/arch/x86/arch_int.c @@ -756,7 +756,7 @@ unexpected_exception(struct iframe* frame) case 13: // General Protection Exception (#GP) type = B_GENERAL_PROTECTION_FAULT; - signal = SIGKILL; + signal = SIGILL; break; case 16: // x87 FPU Floating-Point Error (#MF) @@ -780,9 +780,18 @@ unexpected_exception(struct iframe* frame) } if (IFRAME_IS_USER(frame)) { + struct sigaction action; + struct thread* thread = thread_get_current_thread(); + enable_interrupts(); - if (user_debug_exception_occurred(type, signal)) + // If the thread has a signal handler for the signal, we simply send it + // the signal. Otherwise we notify the user debugger first. + if (sigaction(signal, NULL, &action) == 0 + && action.sa_handler != SIG_DFL + && action.sa_handler != SIG_IGN) { + send_signal(thread->id, SIGSEGV); + } else if (user_debug_exception_occurred(type, signal)) send_signal(team_get_current_team_id(), signal); } else { char name[32]; diff --git a/src/system/kernel/signal.cpp b/src/system/kernel/signal.cpp index 0bef1e92d1..7a8b8617ae 100644 --- a/src/system/kernel/signal.cpp +++ b/src/system/kernel/signal.cpp @@ -383,12 +383,18 @@ handle_signals(struct thread *thread) return true; - case SIGQUIT: + case SIGSEGV: + case SIGFPE: case SIGILL: case SIGTRAP: + // If this is the main thread, we just fall through and let + // this signal kill the team. Otherwise we send a SIGKILL to + // the main thread first, since the signal will kill this + // thread only. + if (thread != thread->team->main_thread) + send_signal(thread->team->main_thread->id, SIGKILL); + case SIGQUIT: case SIGABRT: - case SIGFPE: - case SIGSEGV: case SIGPOLL: case SIGPROF: case SIGSYS: diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index d6ab9302b8..fc41e1e62d 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -4288,9 +4288,9 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, // TODO: the fault_callback is a temporary solution for vm86 if (thread->fault_callback == NULL || thread->fault_callback(address, faultAddress, isWrite)) { - // If the thread has a signal handler for SIGSEGV we simply send - // it the signal. Otherwise we notify the user debugger. If - // anything goes wrong, we kill the team. + // If the thread has a signal handler for SIGSEGV, we simply + // send it the signal. Otherwise we notify the user debugger + // first. struct sigaction action; if (sigaction(SIGSEGV, NULL, &action) == 0 && action.sa_handler != SIG_DFL @@ -4298,7 +4298,7 @@ vm_page_fault(addr_t address, addr_t faultAddress, bool isWrite, bool isUser, send_signal(thread->id, SIGSEGV); } else if (user_debug_exception_occurred(B_SEGMENT_VIOLATION, SIGSEGV)) { - send_signal(team_get_current_team_id(), SIGKILL); + send_signal(thread->id, SIGSEGV); } } }