* Dealt with two debugging related ToDos:

- If the thread's B_THREAD_DEBUG_STOP flag is set, it is now always
    stopped before handling the signals. Unless a SIGKILL[THR] signal is
    pending.
  - Also notify the debugger, when a signal is ignored.
* The signal's sigaction structure is additionally passed to the debugger
  now.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11478 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2005-02-24 16:28:45 +00:00
parent 9c448e2414
commit 260ba6fdd3
+56 -40
View File
@@ -40,6 +40,24 @@ const char * const sigstr[NSIG] = {
}; };
static bool
notify_debugger(int signal, struct sigaction *handler, bool deadly,
cpu_status *state)
{
bool result;
RELEASE_THREAD_LOCK();
restore_interrupts(*state);
result = user_debug_handle_signal(signal, handler, deadly);
*state = disable_interrupts();
GRAB_THREAD_LOCK();
return result;
}
/** /**
* Expects interrupts off and thread lock held. * Expects interrupts off and thread lock held.
* The function may release the lock and enable interrupts temporarily, so the * The function may release the lock and enable interrupts temporarily, so the
@@ -53,33 +71,29 @@ handle_signals(struct thread *thread, cpu_status *state)
int i, sig, global_resched = 0; int i, sig, global_resched = 0;
struct sigaction *handler; struct sigaction *handler;
while (signalMask == 0) { // Check, if the thread shall stop for debugging. It will never stop, if
// check, if the thread shall stop for debugging // a SIGKILL[THR] signal is pending.
// ToDo: This isn't quite right yet. We always need to check if (!(signalMask & (1 << (SIGKILL - 1)))
// whether the thread has to stop, also, if there is a signal. Since && !(signalMask & (1 << (SIGKILLTHR - 1)))
// in case signal debugging is disabled the thread wouldn't stop && thread->debug_info.flags & B_THREAD_DEBUG_STOP) {
// below. At the moment it doesn't stop either, if the signal is RELEASE_THREAD_LOCK();
// ignored. restore_interrupts(*state);
if (thread->debug_info.flags & B_THREAD_DEBUG_STOP) {
RELEASE_THREAD_LOCK();
restore_interrupts(*state);
user_debug_stop_thread(); user_debug_stop_thread();
*state = disable_interrupts(); *state = disable_interrupts();
GRAB_THREAD_LOCK(); GRAB_THREAD_LOCK();
signalMask = thread->sig_pending & (~thread->sig_block_mask); signalMask = thread->sig_pending & (~thread->sig_block_mask);
continue;
}
return 0;
} }
if (signalMask == 0)
return 0;
for (i = 0; i < NSIG; i++) { for (i = 0; i < NSIG; i++) {
if (signalMask & 0x1) { if (signalMask & 0x1) {
bool debugSignal = atomic_get(&thread->team->debug_info.flags) bool debugSignal = !(~atomic_get(&thread->team->debug_info.flags)
& B_TEAM_DEBUG_SIGNALS; & (B_TEAM_DEBUG_SIGNALS | B_TEAM_DEBUG_DEBUGGER_INSTALLED));
sig = i + 1; sig = i + 1;
handler = &thread->sig_action[i]; handler = &thread->sig_action[i];
@@ -91,7 +105,10 @@ handle_signals(struct thread *thread, cpu_status *state)
if (handler->sa_handler == SIG_IGN) { if (handler->sa_handler == SIG_IGN) {
// signal is to be ignored // signal is to be ignored
// ToDo: apply zombie cleaning on SIGCHLD // ToDo: apply zombie cleaning on SIGCHLD
// ToDo: Do we need to notify the debugger?
// notify the debugger
if (debugSignal)
notify_debugger(sig, handler, false, state);
continue; continue;
} }
if (handler->sa_handler == SIG_DFL) { if (handler->sa_handler == SIG_DFL) {
@@ -103,9 +120,18 @@ handle_signals(struct thread *thread, cpu_status *state)
case SIGTTIN: case SIGTTIN:
case SIGTTOU: case SIGTTOU:
case SIGCONT: case SIGCONT:
// notify the debugger
if (debugSignal)
notify_debugger(sig, handler, false, state);
continue; continue;
case SIGSTOP: case SIGSTOP:
// notify the debugger
if (debugSignal) {
if (!notify_debugger(sig, handler, false, state))
continue;
}
thread->next_state = B_THREAD_SUSPENDED; thread->next_state = B_THREAD_SUSPENDED;
global_resched = 1; global_resched = 1;
continue; continue;
@@ -123,6 +149,13 @@ handle_signals(struct thread *thread, cpu_status *state)
if (thread->exit.reason != THREAD_RETURN_EXIT) if (thread->exit.reason != THREAD_RETURN_EXIT)
thread->exit.reason = THREAD_RETURN_INTERRUPTED; thread->exit.reason = THREAD_RETURN_INTERRUPTED;
// notify the debugger
if (debugSignal && sig != SIGKILL
&& sig != SIGKILLTHR) {
if (!notify_debugger(sig, handler, true, state))
continue;
}
RELEASE_THREAD_LOCK(); RELEASE_THREAD_LOCK();
restore_interrupts(*state); restore_interrupts(*state);
@@ -134,31 +167,14 @@ handle_signals(struct thread *thread, cpu_status *state)
// We absolutely need interrupts enabled when we enter // We absolutely need interrupts enabled when we enter
// thread_exit(). // thread_exit().
if (debugSignal && sig != SIGKILL
&& sig != SIGKILLTHR) {
// notify the debugger
if (user_debug_handle_signal(sig, true)
== B_THREAD_DEBUG_IGNORE_SIGNAL) {
continue;
}
}
thread_exit(); thread_exit();
} }
} }
// notify the debugger
if (debugSignal) { if (debugSignal) {
// notify the debugger if (!notify_debugger(sig, handler, false, state))
RELEASE_THREAD_LOCK();
restore_interrupts(*state);
if (user_debug_handle_signal(sig, false)
== B_THREAD_DEBUG_IGNORE_SIGNAL) {
continue; continue;
}
*state = disable_interrupts();
GRAB_THREAD_LOCK();
} }
// ToDo: it's not safe to call arch_setup_signal_frame with // ToDo: it's not safe to call arch_setup_signal_frame with