|
From: Jeremy F. <je...@go...> - 2005-03-01 06:20:23
|
CVS commit by fitzhardinge:
Fix sigsuspend properly. This version should keep everyone happy. eff_sig_mask
has been replaced by tmp_sig_mask; unlike eff_sig_mask, tmp_sig_mask has a very
limit scope, and is just used to communicate the temp signal mask between the
sigsuspend syscall and any signal handlers invoked.
M +7 -6 core.h 1.93
M +1 -1 vg_scheduler.c 1.227
M +21 -22 vg_signals.c 1.135
M +12 -6 vg_syscalls.c 1.257
M +1 -1 linux/core_os.c 1.9
M +3 -3 x86/signal.c 1.16
M +2 -2 x86-linux/syscalls.c 1.26
--- valgrind/coregrind/vg_syscalls.c #1.256:1.257
@@ -1821,5 +1821,5 @@ PRE(sys_execve, Special)
;
- VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->eff_sig_mask, NULL);
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
}
@@ -5499,5 +5499,4 @@ PRE(sys_pause, MayBlock)
}
-// XXX: x86-specific
PRE(sys_sigsuspend, MayBlock)
{
@@ -5515,7 +5514,7 @@ PRE(sys_sigsuspend, MayBlock)
int, history0, int, history1,
vki_old_sigset_t, mask);
+ convert_sigset_to_rt((const vki_old_sigset_t *)arg3, &tst->tmp_sig_mask);
}
-// XXX: x86-specific
PRE(sys_rt_sigsuspend, MayBlock)
{
@@ -5527,7 +5526,9 @@ PRE(sys_rt_sigsuspend, MayBlock)
*/
PRINT("sys_rt_sigsuspend ( %p, %d )", arg1,arg2 );
- PRE_REG_READ2(int, "rt_sigsuspend", vki_sigset_t *, mask, vki_size_t, size)
- if (arg1 != (Addr)NULL)
+ PRE_REG_READ2(int, "rt_sigsuspend", vki_sigset_t *, mask, vki_size_t, size);
+ if (arg1 != (Addr)NULL) {
SYS_PRE_MEM_READ( "rt_sigsuspend(mask)", arg1, sizeof(vki_sigset_t) );
+ tst->tmp_sig_mask = *(vki_sigset_t *)arg1;
+ }
}
@@ -6099,4 +6100,9 @@ void VG_(client_syscall) ( ThreadId tid
tst->syscallno = syscallno;
+ /* Make sure the tmp signal mask matches the real signal
+ mask; sigsuspend may change this. */
+ vg_assert(tst->sig_mask.sig[0] == tst->tmp_sig_mask.sig[0]);
+ vg_assert(tst->sig_mask.sig[1] == tst->tmp_sig_mask.sig[1]);
+
sys = get_syscall_entry(syscallno);
flags = *(sys->flags_ptr);
@@ -6149,5 +6155,5 @@ void VG_(client_syscall) ( ThreadId tid
PRINT(" --> ...\n");
- mask = tst->eff_sig_mask;
+ mask = tst->sig_mask;
VG_(sanitize_client_sigmask)(tid, &mask);
--- valgrind/coregrind/core.h #1.92:1.93
@@ -632,10 +632,11 @@ struct _ThreadState {
vki_sigset_t sig_mask;
- /* Effective signal mask, eff_sig_mask, is usually identical to
- sig_mask, except when running sigsuspend. sigsuspend sets a
- temporary signal mask while it runs, which is retained while any
- signal handler is run; sig_mask comes into effect once the
- handler has finished. */
- vki_sigset_t eff_sig_mask;
+ /* tmp_sig_mask is usually the same as sig_mask, and is kept in
+ sync whenever sig_mask is changed. The only time they have
+ different values is during the execution of a sigsuspend, where
+ tmp_sig_mask is the temporary mask which sigsuspend installs.
+ It is only consulted to compute the signal mask applied to a
+ signal handler. */
+ vki_sigset_t tmp_sig_mask;
/* A little signal queue for signals we can't get the kernel to
--- valgrind/coregrind/vg_signals.c #1.134:1.135
@@ -673,5 +673,5 @@ void do_setmask ( ThreadId tid,
vg_assert(VG_(is_valid_tid)(tid));
if (oldset) {
- *oldset = VG_(threads)[tid].eff_sig_mask;
+ *oldset = VG_(threads)[tid].sig_mask;
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugExtraMsg,
@@ -683,5 +683,5 @@ void do_setmask ( ThreadId tid,
VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGKILL);
VG_(sigdelset)(&VG_(threads)[tid].sig_mask, VKI_SIGSTOP);
- VG_(threads)[tid].eff_sig_mask = VG_(threads)[tid].sig_mask;
+ VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
}
}
@@ -820,5 +820,5 @@ void vg_push_signal_frame ( ThreadId tid
vg_scss.scss_per_sig[sigNo].scss_handler,
vg_scss.scss_per_sig[sigNo].scss_flags,
- &vg_scss.scss_per_sig[sigNo].scss_mask,
+ &tst->sig_mask,
vg_scss.scss_per_sig[sigNo].scss_restorer);
}
@@ -1413,5 +1413,5 @@ static void synth_fault_common(ThreadId
/* If they're trying to block the signal, force it to be delivered */
- if (VG_(sigismember)(&VG_(threads)[tid].eff_sig_mask, VKI_SIGSEGV))
+ if (VG_(sigismember)(&VG_(threads)[tid].sig_mask, VKI_SIGSEGV))
VG_(set_default_handler)(VKI_SIGSEGV);
@@ -1503,13 +1503,18 @@ void VG_(deliver_signal) ( ThreadId tid,
}
- /* Handler gets the union of the signal's mask and the thread's
- mask. The original sigmask has already been saved in the
- signal frame, and will be restored on signal return. */
- VG_(sigaddset_from_set)(&tst->eff_sig_mask, &handler->scss_mask);
- VG_(sigaddset_from_set)(&tst->eff_sig_mask, &VG_(threads)[tid].sig_mask);
+ /* At this point:
+ tst->sig_mask is the current signal mask
+ tst->tmp_sig_mask is the same as sig_mask, unless we're in sigsuspend
+ handler->scss_mask is the mask set by the handler
- /* also mask this signal, unless they ask us not to */
- if (!(handler->scss_flags & VKI_SA_NOMASK))
- VG_(sigaddset)(&tst->eff_sig_mask, sigNo);
+ Handler gets a mask of tmp_sig_mask|handler_mask|signo
+ */
+ tst->sig_mask = tst->tmp_sig_mask;
+ if (!(handler->scss_flags & VKI_SA_NOMASK)) {
+ VG_(sigaddset_from_set)(&tst->sig_mask, &handler->scss_mask);
+ VG_(sigaddset)(&tst->sig_mask, sigNo);
+
+ tst->tmp_sig_mask = tst->sig_mask;
+ }
}
@@ -1621,10 +1626,4 @@ void vg_async_signalhandler ( Int sigNo,
sigNo, tid, info->si_code);
- /* Update the thread's effective signal mask. The only syscall
- this should apply to is sigsuspend, which has a temporary signal
- mask set for signals delivered while it is blocked. The signal
- handler will restore this on signal return. */
- tst->eff_sig_mask = uc->uc_sigmask;
-
/* Update thread state properly */
VGA_(interrupted_syscall)(tid, uc,
@@ -1859,5 +1858,5 @@ void vg_sync_signalhandler ( Int sigNo,
ThreadState *tst = VG_(get_ThreadState)(VG_(get_lwp_tid)(VG_(gettid)()));
- if (VG_(sigismember)(&tst->eff_sig_mask, sigNo)) {
+ if (VG_(sigismember)(&tst->sig_mask, sigNo)) {
/* signal is blocked, but they're not allowed to block faults */
VG_(set_default_handler)(sigNo);
@@ -1985,5 +1984,5 @@ void VG_(poll_signals)(ThreadId tid)
/* look for all the signals this thread isn't blocking */
for(i = 0; i < _VKI_NSIG_WORDS; i++)
- pollset.sig[i] = ~tst->eff_sig_mask.sig[i];
+ pollset.sig[i] = ~tst->sig_mask.sig[i];
VG_(sigdelset)(&pollset, VKI_SIGVGCHLD); /* already dealt with */
@@ -2120,5 +2119,5 @@ void VG_(sigstartup_actions) ( void )
vg_assert(VG_(threads)[VG_(master_tid)].status == VgTs_Init);
VG_(threads)[VG_(master_tid)].sig_mask = saved_procmask;
- VG_(threads)[VG_(master_tid)].eff_sig_mask = saved_procmask;
+ VG_(threads)[VG_(master_tid)].tmp_sig_mask = saved_procmask;
/* Calculate SKSS and apply it. This also sets the initial kernel
--- valgrind/coregrind/vg_scheduler.c #1.226:1.227
@@ -509,5 +509,5 @@ void mostly_clear_thread_record ( Thread
VG_(sigemptyset)(&VG_(threads)[tid].sig_mask);
- VG_(sigemptyset)(&VG_(threads)[tid].eff_sig_mask);
+ VG_(sigemptyset)(&VG_(threads)[tid].tmp_sig_mask);
VGA_(os_state_clear)(&VG_(threads)[tid]);
--- valgrind/coregrind/x86-linux/syscalls.c #1.25:1.26
@@ -327,6 +327,6 @@ static Int do_clone(ThreadId ptid,
/* inherit signal mask */
- ctst->sig_mask = ptst->eff_sig_mask;
- ctst->eff_sig_mask = ctst->sig_mask;
+ ctst->sig_mask = ptst->sig_mask;
+ ctst->tmp_sig_mask = ptst->sig_mask;
/* We don't really know where the client stack is, because its
--- valgrind/coregrind/linux/core_os.c #1.8:1.9
@@ -125,5 +125,5 @@ void VGA_(final_tidyup)(ThreadId tid)
the thread's block state*/
VG_(sigprocmask)(VKI_SIG_BLOCK, NULL, &VG_(threads)[tid].sig_mask);
- VG_(threads)[tid].eff_sig_mask = VG_(threads)[tid].sig_mask;
+ VG_(threads)[tid].tmp_sig_mask = VG_(threads)[tid].sig_mask;
/* and restore handlers to default */
--- valgrind/coregrind/x86/signal.c #1.15:1.16
@@ -454,5 +454,5 @@ static Addr build_sigframe(ThreadState *
VG_(memcpy)(&frame->sigContext, &uc.uc_mcontext,
sizeof(struct vki_sigcontext));
- frame->sigContext.oldmask = tst->sig_mask.sig[0];
+ frame->sigContext.oldmask = mask->sig[0];
VG_TRACK( post_mem_write, esp, offsetof(struct sigframe, vg) );
@@ -554,5 +554,5 @@ static Bool restore_vg_sigframe(ThreadSt
tst->sig_mask = frame->mask;
- tst->eff_sig_mask = frame->mask;
+ tst->tmp_sig_mask = frame->mask;
if (VG_(needs).shadow_regs) {
|