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
This commit is contained in:
Ingo Weinhold
2008-09-27 14:08:13 +00:00
parent 02e08b15ef
commit 7805eb0cc2
3 changed files with 24 additions and 9 deletions
+11 -2
View File
@@ -756,7 +756,7 @@ unexpected_exception(struct iframe* frame)
case 13: // General Protection Exception (#GP) case 13: // General Protection Exception (#GP)
type = B_GENERAL_PROTECTION_FAULT; type = B_GENERAL_PROTECTION_FAULT;
signal = SIGKILL; signal = SIGILL;
break; break;
case 16: // x87 FPU Floating-Point Error (#MF) case 16: // x87 FPU Floating-Point Error (#MF)
@@ -780,9 +780,18 @@ unexpected_exception(struct iframe* frame)
} }
if (IFRAME_IS_USER(frame)) { if (IFRAME_IS_USER(frame)) {
struct sigaction action;
struct thread* thread = thread_get_current_thread();
enable_interrupts(); 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); send_signal(team_get_current_team_id(), signal);
} else { } else {
char name[32]; char name[32];
+9 -3
View File
@@ -383,12 +383,18 @@ handle_signals(struct thread *thread)
return true; return true;
case SIGQUIT: case SIGSEGV:
case SIGFPE:
case SIGILL: case SIGILL:
case SIGTRAP: 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 SIGABRT:
case SIGFPE:
case SIGSEGV:
case SIGPOLL: case SIGPOLL:
case SIGPROF: case SIGPROF:
case SIGSYS: case SIGSYS:
+4 -4
View File
@@ -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 // TODO: the fault_callback is a temporary solution for vm86
if (thread->fault_callback == NULL if (thread->fault_callback == NULL
|| thread->fault_callback(address, faultAddress, isWrite)) { || thread->fault_callback(address, faultAddress, isWrite)) {
// If the thread has a signal handler for SIGSEGV we simply send // If the thread has a signal handler for SIGSEGV, we simply
// it the signal. Otherwise we notify the user debugger. If // send it the signal. Otherwise we notify the user debugger
// anything goes wrong, we kill the team. // first.
struct sigaction action; struct sigaction action;
if (sigaction(SIGSEGV, NULL, &action) == 0 if (sigaction(SIGSEGV, NULL, &action) == 0
&& action.sa_handler != SIG_DFL && 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); send_signal(thread->id, SIGSEGV);
} else if (user_debug_exception_occurred(B_SEGMENT_VIOLATION, } else if (user_debug_exception_occurred(B_SEGMENT_VIOLATION,
SIGSEGV)) { SIGSEGV)) {
send_signal(team_get_current_team_id(), SIGKILL); send_signal(thread->id, SIGSEGV);
} }
} }
} }