/* Max number of callers for context in a suppression. */
#define VG_N_SUPP_CALLERS 4
+/* Numer of entries in each thread's signal queue. */
+#define VG_N_SIGNALQUEUE 8
+
/* Useful macros */
/* a - alignment - must be a power of 2 */
#define ROUNDDN(p, a) ((Addr)(p) & ~((a)-1))
*/
vki_ksigset_t eff_sig_mask;
+ /* Signal queue. This is used when the kernel doesn't route
+ signals properly in order to remember the signal information
+ while we are routing the signal. It is a circular queue with
+ insertions performed at the head and removals at the tail.
+ */
+ vki_ksiginfo_t sigqueue[VG_N_SIGNALQUEUE];
+ Int sigqueue_head;
+ Int sigqueue_tail;
+
/* Stacks. When a thread slot is freed, we don't deallocate its
stack; we just leave it lying around for the next use of the
slot. If the next use of the slot requires a larger stack,
break;
case PX_Signal:
- if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
+ if (VG_(do_signal_routing) &&
+ res.u.siginfo.si_code == VKI_SI_USER &&
+ res.u.siginfo._sifields._kill._pid == VG_(getpid)()) {
+ Int ptr = tst->sigqueue_tail;
+
+ while (tst->sigqueue[ptr].si_signo != res.u.siginfo.si_signo) {
+ vg_assert(ptr != tst->sigqueue_head);
+ ptr = (ptr + 1) % VG_N_SIGNALQUEUE;
+ }
+
+ res.u.siginfo = tst->sigqueue[ptr];
+ tst->sigqueue[ptr].si_signo = 0;
+
+ while (tst->sigqueue_tail != tst->sigqueue_head &&
+ tst->sigqueue[tst->sigqueue_tail].si_signo == 0) {
+ tst->sigqueue_tail = (tst->sigqueue_tail + 1) % VG_N_SIGNALQUEUE;
+ }
+ }
+
+ if (VG_(clo_trace_signals) || VG_(clo_trace_syscalls))
VG_(message)(Vg_DebugMsg, "sys_wait_results: got PX_Signal for TID %d, signal %d",
res.tid, res.u.siginfo.si_signo);
VG_(threads)[tid].custack_used = 0;
VG_(ksigemptyset)(&VG_(threads)[tid].sig_mask);
VG_(ksigfillset)(&VG_(threads)[tid].eff_sig_mask);
+ VG_(threads)[tid].sigqueue_head = 0;
+ VG_(threads)[tid].sigqueue_tail = 0;
VG_(threads)[tid].specifics_ptr = NULL;
VG_(threads)[tid].syscallno = -1;
static const struct vki_timespec zero = { 0, 0 };
static ThreadId start_tid = 1; /* tid to start scanning from */
vki_ksigset_t set;
+ vki_ksiginfo_t siset[VKI_KNSIG];
vki_ksiginfo_t si;
Int sigNo;
VG_(block_all_host_signals) ( &set );
/* grab any pending signals and add them to the pending signal set */
- while(VG_(ksigtimedwait)(&set, &si, &zero) > 0)
+ while(VG_(ksigtimedwait)(&set, &si, &zero) > 0) {
VG_(ksigaddset)(&proc_pending, si.si_signo);
+ siset[si.si_signo] = si;
+ }
/* transfer signals from the process pending set to a particular
thread which has it unblocked */
/* found one - deliver it and be done */
if (target != -1) {
+ ThreadState *tst = &VG_(threads)[target];
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugMsg, "Routing signal %d to tid %d",
sigNo, tid);
+ tst->sigqueue[tst->sigqueue_head] = siset[sigNo];
+ tst->sigqueue_head = (tst->sigqueue_head + 1) % VG_N_SIGNALQUEUE;
+ vg_assert(tst->sigqueue_head != tst->sigqueue_tail);
VG_(proxy_sendsig)(target, sigNo);
VG_(ksigdelset)(&proc_pending, sigNo);
}