|
From: Tom H. <th...@cy...> - 2004-10-16 10:59:52
|
CVS commit by thughes:
When signal routing is in use (because we are running on an older kernel
that doesn't route signals to the correct threads properly) the siginfo
data was not being propagated to any signal handlers installed by the
client program.
This is because the main thread routes the signal to the proxy LWP by
using the tkill system call but that then appears in the proxy as a user
initiated signal and the original siginfo data is lost.
This patch adds a small queue of siginfo data for pending sigals to
each thread's state so that when the proxy LWP passes the signal back
to the main thread the relevant siginfo data can be recovered and passed
on to any signal handlers. Thix fixes bug 91325.
M +12 -0 core.h 1.35
M +20 -1 vg_proxylwp.c 1.23
M +2 -0 vg_scheduler.c 1.187
M +8 -1 vg_signals.c 1.94
--- valgrind/coregrind/core.h #1.34:1.35
@@ -177,4 +177,7 @@
#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 */
@@ -813,4 +816,13 @@ typedef
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
--- valgrind/coregrind/vg_proxylwp.c #1.22:1.23
@@ -1154,4 +1154,23 @@ static void sys_wait_results(Bool block,
case PX_Signal:
+ 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",
--- valgrind/coregrind/vg_scheduler.c #1.186:1.187
@@ -373,4 +373,6 @@ void mostly_clear_thread_record ( Thread
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;
--- valgrind/coregrind/vg_signals.c #1.93:1.94
@@ -1919,4 +1919,5 @@ void VG_(route_signals)(void)
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;
@@ -1934,6 +1935,8 @@ void VG_(route_signals)(void)
/* 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
@@ -1970,7 +1973,11 @@ void VG_(route_signals)(void)
/* 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);
|