* 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:
+56
-40
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user