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,