]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
When signal routing is in use (because we are running on an older kernel
authorTom Hughes <tom@compton.nu>
Sat, 16 Oct 2004 10:59:49 +0000 (10:59 +0000)
committerTom Hughes <tom@compton.nu>
Sat, 16 Oct 2004 10:59:49 +0000 (10:59 +0000)
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.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2773

coregrind/core.h
coregrind/vg_proxylwp.c
coregrind/vg_scheduler.c
coregrind/vg_signals.c

index 197fe887d4c99083ba4499a601061ce5ca486f79..afc316177ab9e3554088448db87bc33a488ed3d5 100644 (file)
 /* 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))
@@ -812,6 +815,15 @@ 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
       slot.  If the next use of the slot requires a larger stack,
index 885644411632f2d5b351adf0f48e8a9fd925279b..de25bc16976046e5151196977939a26e294ebb79 100644 (file)
@@ -1153,7 +1153,26 @@ static void sys_wait_results(Bool block, ThreadId tid, enum RequestType reqtype,
            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);
 
index 7de3f220fc0a46b59e15249f364c9da13dbcf48f..1252f7df5aba0998f2f8a8c0e51d8dda6582722b 100644 (file)
@@ -372,6 +372,8 @@ void mostly_clear_thread_record ( ThreadId tid )
    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;
index 4d46e48f165710eb6e69138a132eca3f7afb2d62..57c146810e6a64d4a33455ad359034705e87b637 100644 (file)
@@ -1918,6 +1918,7 @@ void VG_(route_signals)(void)
    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;
 
@@ -1933,8 +1934,10 @@ void VG_(route_signals)(void)
    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 */
@@ -1969,9 +1972,13 @@ 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);
       }