extern void VG_(proxy_create) ( ThreadId tid );
extern void VG_(proxy_delete) ( ThreadId tid, Bool force );
extern void VG_(proxy_results) ( void );
-extern void VG_(proxy_sendsig) ( ThreadId tid, Int signo );
+extern void VG_(proxy_sendsig) ( ThreadId fromTid, ThreadId toTid, Int signo );
extern void VG_(proxy_setsigmask)(ThreadId tid);
extern void VG_(proxy_sigack) ( ThreadId tid, const vki_sigset_t *);
extern void VG_(proxy_abort_syscall) ( ThreadId tid );
}
/* Send a signal to a proxy LWP */
-void VG_(proxy_sendsig)(ThreadId tid, Int sig)
+void VG_(proxy_sendsig)(ThreadId fromTid, ThreadId toTid, Int sig)
{
- ThreadState *tst = VG_(get_ThreadState)(tid);
- ProxyLWP *proxy = tst->proxy;
- Int lwp;
+ /* toTid must be genuine, but fromTid can be
+ VG_INVALID_THREADID. */
+ ThreadState* tst = VG_(get_ThreadState)(toTid);
+ ProxyLWP* proxy = tst->proxy;
+ Bool signallingMyself;
+ Int lwp;
if (proxy == NULL)
return;
/* If a thread is sending a signal to itself and the signal isn't
blocked (ie, it will be delivered), wait until the signal
message gets sent back, thus making the signal synchronous. */
+ signallingMyself
+ = fromTid != VG_INVALID_THREADID
+ && fromTid == toTid;
+
if (sig != 0 &&
!VG_(is_sig_ign)(sig) &&
- tid == VG_(get_current_tid)() &&
+ signallingMyself &&
!VG_(sigismember)(&tst->eff_sig_mask, sig)) {
/* If the LWP is actually blocked in a sigtimedwait, then it
will eat the signal rather than make it pending and deliver
it by the normal mechanism. In this case, just wait for the
syscall to dinish. */
if (tst->status == VgTs_WaitSys && tst->syscallno == __NR_rt_sigtimedwait)
- sys_wait_results(True, tid, PX_RunSyscall, True);
+ sys_wait_results(True, toTid, PX_RunSyscall, True);
else
- sys_wait_results(True, tid, PX_Signal, True);
+ sys_wait_results(True, toTid, PX_Signal, True);
}
}
tst = VG_(get_ThreadState)(thread);
vg_assert(NULL != tst->proxy);
- VG_(proxy_sendsig)(thread, sig);
+ VG_(proxy_sendsig)(tid/*from*/, thread/*to*/, sig);
SET_PTHREQ_RETVAL(tid, 0);
}
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_(proxy_sendsig)(VG_INVALID_THREADID/*from*/,
+ target/*to*/, sigNo);
VG_(sigdelset)(&proc_pending, sigNo);
}
}