bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 12/15] Hurd signals: fix global untraced signals.


From: Jeremie Koenig
Subject: [PATCH 12/15] Hurd signals: fix global untraced signals.
Date: Wed, 29 Jun 2011 18:30:24 +0200

Delivering global signals by making them temporarily pending in the
global mask looses their untracedness status, so we need to deliver them
directly whenever we can.

* hurd/hurdsig.c (post_signal): Attempt to find a receiver thread right
away for global signals.
---
 hurd/hurdsig.c |   46 +++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
index f5fa659..0125ccb 100644
--- a/hurd/hurdsig.c
+++ b/hurd/hurdsig.c
@@ -577,9 +577,11 @@ weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
                  sigmask (SIGSTOP) | sigmask (SIGTSTP))
 
 /* Actual delivery of a single signal.  Called with SS unlocked.  When
-   the signal is delivered, return 1 with SS locked.  If the signal is
-   being traced, return 0 with SS unlocked.   */
-static int
+   the signal is delivered, return SS, locked (or, if SS was originally
+   _hurd_global_sigstate, the sigstate of the actual thread the signal
+   was delivered to).  If the signal is being traced, return NULL with
+   SS unlocked.   */
+static struct hurd_sigstate *
 post_signal (struct hurd_sigstate *ss,
             int signo, struct hurd_signal_detail *detail,
             int untraced, void (*reply) (void))
@@ -666,13 +668,38 @@ post_signal (struct hurd_sigstate *ss,
 
       /* This call is just to check for pending signals.  */
       _hurd_sigstate_lock (ss);
-      return 1;
+      return ss;
     }
 
   thread_state.set = 0;                /* We know nothing.  */
 
   _hurd_sigstate_lock (ss);
 
+  /* If this is a global signal, try to find a thread ready to accept
+     it right away.  This is especially important for untraced signals,
+     since going through the global pending mask would de-untrace them.  */
+  if (ss->thread == MACH_PORT_NULL)
+  {
+    struct hurd_sigstate *rss;
+
+    __mutex_lock (&_hurd_siglock);
+    for (rss = _hurd_sigstates; rss != NULL; rss = rss->next)
+      {
+       if (! sigstate_is_global_rcv (rss))
+         continue;
+
+       /* The global sigstate is already locked.  */
+       __spin_lock (&rss->lock);
+       if (! __sigismember (&rss->blocked, signo))
+         {
+           ss = rss;
+           break;
+         }
+       __spin_unlock (&rss->lock);
+      }
+    __mutex_unlock (&_hurd_siglock);
+  }
+
   /* Check for a preempted signal.  Preempted signals can arrive during
      critical sections.  */
   /* XXX how does this mix with _hurd_global_sigstate?  Should its PREEMPTORS
@@ -733,7 +760,7 @@ post_signal (struct hurd_sigstate *ss,
            suspend ();
          _hurd_sigstate_unlock (ss);
          reply ();
-         return 0;
+         return NULL;
        }
 
       handler = _hurd_sigstate_actions (ss) [signo].sa_handler;
@@ -1083,7 +1110,7 @@ post_signal (struct hurd_sigstate *ss,
       }
     }
 
-  return 1;
+  return ss;
 }
 
 /* Return the set of pending signals in SS which should be delivered. */
@@ -1110,6 +1137,10 @@ post_pending (struct hurd_sigstate *ss, sigset_t 
pending, void (*reply) (void))
   int signo;
   struct hurd_signal_detail detail;
 
+  /* Make sure SS corresponds to an actual thread, since we assume it won't
+     change in post_signal. */
+  assert (ss->thread != MACH_PORT_NULL);
+
   for (signo = 1; signo < NSIG; ++signo)
     if (__sigismember (&pending, signo))
       {
@@ -1180,7 +1211,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
        assert_perror (err);
     }
 
-  if (! post_signal (ss, signo, detail, untraced, reply))
+  ss = post_signal (ss, signo, detail, untraced, reply);
+  if (! ss)
     return;
 
   /* The signal was neither fatal nor traced.  We still hold SS->lock.  */
-- 
1.7.5.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]