* 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) {
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;
}
}

View File

@ -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);

View File

@ -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,