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:
@@ -252,6 +252,7 @@ struct thread {
|
|||||||
|
|
||||||
sigset_t sig_pending;
|
sigset_t sig_pending;
|
||||||
sigset_t sig_block_mask;
|
sigset_t sig_block_mask;
|
||||||
|
sigset_t sig_temp_enabled;
|
||||||
struct sigaction sig_action[32];
|
struct sigaction sig_action[32];
|
||||||
addr_t signal_stack_base;
|
addr_t signal_stack_base;
|
||||||
size_t signal_stack_size;
|
size_t signal_stack_size;
|
||||||
|
|||||||
@@ -263,7 +263,9 @@ class SigSuspendDone : public AbstractTraceEntry {
|
|||||||
static void
|
static void
|
||||||
update_thread_signals_flag(struct thread* thread)
|
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);
|
atomic_or(&thread->flags, THREAD_FLAGS_SIGNALS_PENDING);
|
||||||
else
|
else
|
||||||
atomic_and(&thread->flags, ~THREAD_FLAGS_SIGNALS_PENDING);
|
atomic_and(&thread->flags, ~THREAD_FLAGS_SIGNALS_PENDING);
|
||||||
@@ -307,7 +309,8 @@ bool
|
|||||||
handle_signals(struct thread *thread)
|
handle_signals(struct thread *thread)
|
||||||
{
|
{
|
||||||
uint32 signalMask = atomic_get(&thread->sig_pending)
|
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.
|
// If SIGKILL[THR] are pending, we ignore other signals.
|
||||||
// Otherwise check, if the thread shall stop for debugging.
|
// Otherwise check, if the thread shall stop for debugging.
|
||||||
@@ -904,6 +907,8 @@ sigsuspend(const sigset_t *mask)
|
|||||||
// restore the original block mask
|
// restore the original block mask
|
||||||
atomic_set(&thread->sig_block_mask, oldMask);
|
atomic_set(&thread->sig_block_mask, oldMask);
|
||||||
|
|
||||||
|
thread->sig_temp_enabled = ~*mask;
|
||||||
|
|
||||||
update_current_thread_signals_flag();
|
update_current_thread_signals_flag();
|
||||||
|
|
||||||
T(SigSuspendDone());
|
T(SigSuspendDone());
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ reset_signals(struct thread *thread)
|
|||||||
{
|
{
|
||||||
thread->sig_pending = 0;
|
thread->sig_pending = 0;
|
||||||
thread->sig_block_mask = 0;
|
thread->sig_block_mask = 0;
|
||||||
|
thread->sig_temp_enabled = 0;
|
||||||
memset(thread->sig_action, 0, 32 * sizeof(struct sigaction));
|
memset(thread->sig_action, 0, 32 * sizeof(struct sigaction));
|
||||||
thread->signal_stack_base = 0;
|
thread->signal_stack_base = 0;
|
||||||
thread->signal_stack_size = 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);
|
kprintf("(%d)\n", thread->cpu->cpu_num);
|
||||||
else
|
else
|
||||||
kprintf("\n");
|
kprintf("\n");
|
||||||
kprintf("sig_pending: %#lx (blocked: %#lx)\n", thread->sig_pending,
|
kprintf("sig_pending: %#" B_PRIx32 " (blocked: %#" B_PRIx32
|
||||||
thread->sig_block_mask);
|
", temp enabled: %#" B_PRIx32 ")\n", thread->sig_pending,
|
||||||
|
thread->sig_block_mask, thread->sig_temp_enabled);
|
||||||
kprintf("in_kernel: %d\n", thread->in_kernel);
|
kprintf("in_kernel: %d\n", thread->in_kernel);
|
||||||
|
|
||||||
if (thread->state == B_THREAD_WAITING) {
|
if (thread->state == B_THREAD_WAITING) {
|
||||||
|
|||||||
Reference in New Issue
Block a user