From 871d97a9f50e5b5ce5aee37c98bc83c2a519f2f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Fri, 17 Aug 2007 13:08:24 +0000 Subject: [PATCH] * Fixed the kernel bug that prevented SIGCONT from working properly: the problem occured if SIGSTOP was already delivered but not yet handled when SIGCONT was sent. Now, SIGCONT will clear all stop signals from the pending signals. * SIGTSTP, SIGTTIN, and SIGTTOU are supposed to suspend the thread as well, adapted the default behaviour to respect that. * Removed the work-around from r21997 TermParse.cpp for this exact problem. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22004 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/terminal/TermParse.cpp | 11 +++++------ src/system/kernel/signal.c | 22 ++++++++++++++++------ src/system/kernel/thread.c | 2 +- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/apps/terminal/TermParse.cpp b/src/apps/terminal/TermParse.cpp index 8de49fbb5c..63a26e0db2 100644 --- a/src/apps/terminal/TermParse.cpp +++ b/src/apps/terminal/TermParse.cpp @@ -225,12 +225,11 @@ TermParse::StopPtyReader() } if (fReaderThread >= 0) { - status_t dummy; - //suspend_thread(fReaderThread); - // TODO: interrupt read() - doesn't work for whatever reason - //wait_for_thread(fReaderThread, &dummy); - kill_thread(fReaderThread); - + suspend_thread(fReaderThread); + + status_t status; + wait_for_thread(fReaderThread, &status); + fReaderThread = -1; } } diff --git a/src/system/kernel/signal.c b/src/system/kernel/signal.c index d18dc91456..9d44399826 100644 --- a/src/system/kernel/signal.c +++ b/src/system/kernel/signal.c @@ -32,8 +32,12 @@ #define SIGNAL_TO_MASK(signal) (1LL << (signal - 1)) #define BLOCKABLE_SIGNALS (~(KILL_SIGNALS | SIGNAL_TO_MASK(SIGSTOP))) +#define STOP_SIGNALS \ + (SIGNAL_TO_MASK(SIGSTOP) | SIGNAL_TO_MASK(SIGTSTP) \ + | SIGNAL_TO_MASK(SIGTTIN) | SIGNAL_TO_MASK(SIGTTOU)) #define DEFAULT_IGNORE_SIGNALS \ - (SIGNAL_TO_MASK(SIGCHLD) | SIGNAL_TO_MASK(SIGWINCH) | SIGNAL_TO_MASK(SIGCONT)) + (SIGNAL_TO_MASK(SIGCHLD) | SIGNAL_TO_MASK(SIGWINCH) \ + | SIGNAL_TO_MASK(SIGCONT)) const char * const sigstr[NSIG] = { @@ -128,9 +132,6 @@ handle_signals(struct thread *thread) switch (signal) { case SIGCHLD: case SIGWINCH: - case SIGTSTP: - case SIGTTIN: - case SIGTTOU: case SIGCONT: case SIGURG: // notify the debugger @@ -139,6 +140,9 @@ handle_signals(struct thread *thread) continue; case SIGSTOP: + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: // notify the debugger if (debugSignal && !notify_debugger(thread, signal, handler, false)) @@ -212,7 +216,8 @@ handle_signals(struct thread *thread) bool is_kill_signal_pending(void) { - return (atomic_get(&thread_get_current_thread()->sig_pending) & KILL_SIGNALS) != 0; + return (atomic_get(&thread_get_current_thread()->sig_pending) + & KILL_SIGNALS) != 0; } @@ -267,16 +272,21 @@ deliver_signal(struct thread *thread, uint signal, uint32 flags) } else if (thread->state == B_THREAD_WAITING) sem_interrupt_thread(thread); break; + case SIGCONT: // Wake up thread if it was suspended if (thread->state == B_THREAD_SUSPENDED) { thread->state = thread->next_state = B_THREAD_READY; scheduler_enqueue_in_run_queue(thread); } + + atomic_and(&thread->sig_pending, ~STOP_SIGNALS); + // remove any pending stop signals break; default: - if (thread->sig_pending & (~thread->sig_block_mask | SIGNAL_TO_MASK(SIGCHLD))) { + if (thread->sig_pending + & (~thread->sig_block_mask | SIGNAL_TO_MASK(SIGCHLD))) { // Interrupt thread if it was waiting if (thread->state == B_THREAD_WAITING) sem_interrupt_thread(thread); diff --git a/src/system/kernel/thread.c b/src/system/kernel/thread.c index d451530c76..c515822429 100644 --- a/src/system/kernel/thread.c +++ b/src/system/kernel/thread.c @@ -1529,7 +1529,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout, if (thread == NULL) { // we couldn't find this thread - maybe it's already gone, and we'll - // find its death entry + // find its death entry in our team GRAB_TEAM_LOCK(); status = team_get_death_entry(thread_get_current_thread()->team,