sigsuspend() would previously wake up correctly when a matching signal was

received, but if the signal was in the thread's signal block mask, it would
not be handled. Added thread::sig_temp_enabled, an additional mask of not
blocked signals, which is set by sigsuspend() and evaluated and reset by
handle_signals(). Fixes #5567.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35836 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-03-13 13:17:40 +00:00
parent 5975d86a38
commit 7778bccf93
3 changed files with 12 additions and 4 deletions

View File

@ -252,6 +252,7 @@ struct thread {
sigset_t sig_pending;
sigset_t sig_block_mask;
sigset_t sig_temp_enabled;
struct sigaction sig_action[32];
addr_t signal_stack_base;
size_t signal_stack_size;

View File

@ -263,7 +263,9 @@ class SigSuspendDone : public AbstractTraceEntry {
static void
update_thread_signals_flag(struct thread* thread)
{
if (atomic_get(&thread->sig_pending) & ~atomic_get(&thread->sig_block_mask))
sigset_t mask = ~atomic_get(&thread->sig_block_mask)
| thread->sig_temp_enabled;
if (atomic_get(&thread->sig_pending) & mask)
atomic_or(&thread->flags, THREAD_FLAGS_SIGNALS_PENDING);
else
atomic_and(&thread->flags, ~THREAD_FLAGS_SIGNALS_PENDING);
@ -307,7 +309,8 @@ bool
handle_signals(struct thread *thread)
{
uint32 signalMask = atomic_get(&thread->sig_pending)
& ~atomic_get(&thread->sig_block_mask);
& (~atomic_get(&thread->sig_block_mask) | thread->sig_temp_enabled);
thread->sig_temp_enabled = 0;
// If SIGKILL[THR] are pending, we ignore other signals.
// Otherwise check, if the thread shall stop for debugging.
@ -904,6 +907,8 @@ sigsuspend(const sigset_t *mask)
// restore the original block mask
atomic_set(&thread->sig_block_mask, oldMask);
thread->sig_temp_enabled = ~*mask;
update_current_thread_signals_flag();
T(SigSuspendDone());

View File

@ -195,6 +195,7 @@ reset_signals(struct thread *thread)
{
thread->sig_pending = 0;
thread->sig_block_mask = 0;
thread->sig_temp_enabled = 0;
memset(thread->sig_action, 0, 32 * sizeof(struct sigaction));
thread->signal_stack_base = 0;
thread->signal_stack_size = 0;
@ -1164,8 +1165,9 @@ _dump_thread_info(struct thread *thread, bool shortInfo)
kprintf("(%d)\n", thread->cpu->cpu_num);
else
kprintf("\n");
kprintf("sig_pending: %#lx (blocked: %#lx)\n", thread->sig_pending,
thread->sig_block_mask);
kprintf("sig_pending: %#" B_PRIx32 " (blocked: %#" B_PRIx32
", temp enabled: %#" B_PRIx32 ")\n", thread->sig_pending,
thread->sig_block_mask, thread->sig_temp_enabled);
kprintf("in_kernel: %d\n", thread->in_kernel);
if (thread->state == B_THREAD_WAITING) {