* 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
This commit is contained in:
Axel Dörfler 2007-08-17 13:08:24 +00:00
parent f7e1df7560
commit 871d97a9f5
3 changed files with 22 additions and 13 deletions

View File

@ -225,12 +225,11 @@ TermParse::StopPtyReader()
} }
if (fReaderThread >= 0) { if (fReaderThread >= 0) {
status_t dummy; suspend_thread(fReaderThread);
//suspend_thread(fReaderThread);
// TODO: interrupt read() - doesn't work for whatever reason status_t status;
//wait_for_thread(fReaderThread, &dummy); wait_for_thread(fReaderThread, &status);
kill_thread(fReaderThread);
fReaderThread = -1; fReaderThread = -1;
} }
} }

View File

@ -32,8 +32,12 @@
#define SIGNAL_TO_MASK(signal) (1LL << (signal - 1)) #define SIGNAL_TO_MASK(signal) (1LL << (signal - 1))
#define BLOCKABLE_SIGNALS (~(KILL_SIGNALS | SIGNAL_TO_MASK(SIGSTOP))) #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 \ #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] = { const char * const sigstr[NSIG] = {
@ -128,9 +132,6 @@ handle_signals(struct thread *thread)
switch (signal) { switch (signal) {
case SIGCHLD: case SIGCHLD:
case SIGWINCH: case SIGWINCH:
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
case SIGCONT: case SIGCONT:
case SIGURG: case SIGURG:
// notify the debugger // notify the debugger
@ -139,6 +140,9 @@ handle_signals(struct thread *thread)
continue; continue;
case SIGSTOP: case SIGSTOP:
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
// notify the debugger // notify the debugger
if (debugSignal if (debugSignal
&& !notify_debugger(thread, signal, handler, false)) && !notify_debugger(thread, signal, handler, false))
@ -212,7 +216,8 @@ handle_signals(struct thread *thread)
bool bool
is_kill_signal_pending(void) 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) } else if (thread->state == B_THREAD_WAITING)
sem_interrupt_thread(thread); sem_interrupt_thread(thread);
break; break;
case SIGCONT: case SIGCONT:
// Wake up thread if it was suspended // Wake up thread if it was suspended
if (thread->state == B_THREAD_SUSPENDED) { if (thread->state == B_THREAD_SUSPENDED) {
thread->state = thread->next_state = B_THREAD_READY; thread->state = thread->next_state = B_THREAD_READY;
scheduler_enqueue_in_run_queue(thread); scheduler_enqueue_in_run_queue(thread);
} }
atomic_and(&thread->sig_pending, ~STOP_SIGNALS);
// remove any pending stop signals
break; break;
default: 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 // Interrupt thread if it was waiting
if (thread->state == B_THREAD_WAITING) if (thread->state == B_THREAD_WAITING)
sem_interrupt_thread(thread); sem_interrupt_thread(thread);

View File

@ -1529,7 +1529,7 @@ wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
if (thread == NULL) { if (thread == NULL) {
// we couldn't find this thread - maybe it's already gone, and we'll // 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(); GRAB_TEAM_LOCK();
status = team_get_death_entry(thread_get_current_thread()->team, status = team_get_death_entry(thread_get_current_thread()->team,