If no thread can immediately handle a signal, which has been sent
authorbluhm <bluhm@openbsd.org>
Wed, 11 Jul 2018 19:28:16 +0000 (19:28 +0000)
committerbluhm <bluhm@openbsd.org>
Wed, 11 Jul 2018 19:28:16 +0000 (19:28 +0000)
to the process, it is made pending at the main thread.  There it
could hang forever.  So also check the main thread for signal
delivery.  This workaround fixes hung tests in posixtestsuite.  The
proper solution would be to split pending signals for process and
threads.
input visa@; OK guenther@

sys/kern/kern_sig.c
sys/sys/signalvar.h

index 823ab10..7a8a7a9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_sig.c,v 1.221 2018/07/10 04:19:59 guenther Exp $ */
+/*     $OpenBSD: kern_sig.c,v 1.222 2018/07/11 19:28:16 bluhm Exp $    */
 /*     $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $   */
 
 /*
@@ -1153,14 +1153,17 @@ issignal(struct proc *p)
        int s;
 
        for (;;) {
-               mask = p->p_siglist & ~p->p_sigmask;
+               mask = SIGPENDING(p);
                if (pr->ps_flags & PS_PPWAIT)
                        mask &= ~stopsigmask;
                if (mask == 0)          /* no signal to send */
                        return (0);
                signum = ffs((long)mask);
                mask = sigmask(signum);
-               atomic_clearbits_int(&p->p_siglist, mask);
+               if (p->p_siglist & mask)
+                       atomic_clearbits_int(&p->p_siglist, mask);
+               else
+                       atomic_clearbits_int(&pr->ps_mainproc->p_siglist, mask);
 
                /*
                 * We should see pending but ignored signals
@@ -1836,7 +1839,7 @@ userret(struct proc *p)
                KERNEL_UNLOCK();
        }
 
-       if (SIGPENDING(p)) {
+       if (SIGPENDING(p) != 0) {
                KERNEL_LOCK();
                while ((signum = CURSIG(p)) != 0)
                        postsig(p, signum);
index dd36d73..f5e0a07 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: signalvar.h,v 1.31 2018/07/10 04:19:59 guenther Exp $ */
+/*     $OpenBSD: signalvar.h,v 1.32 2018/07/11 19:28:16 bluhm Exp $    */
 /*     $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $  */
 
 /*
@@ -68,7 +68,9 @@ struct        sigacts {
 /*
  * Check if process p has an unmasked signal pending.
  */
-#define        SIGPENDING(p)   (((p)->p_siglist & ~(p)->p_sigmask) != 0)
+#define        SIGPENDING(p)                                                   \
+       (((p)->p_siglist | (p)->p_p->ps_mainproc->p_siglist) &          \
+           ~(p)->p_sigmask)
 
 /*
  * Determine signal that should be delivered to process p, the current
@@ -76,10 +78,9 @@ struct       sigacts {
  * action, the process stops in issignal().
  */
 #define        CURSIG(p)                                                       \
-       (((p)->p_siglist == 0 ||                                        \
-           (((p)->p_p->ps_flags & PS_TRACED) == 0 &&                   \
-           ((p)->p_siglist & ~(p)->p_sigmask) == 0)) ?                 \
-           0 : issignal(p))
+       (((((p)->p_siglist | (p)->p_p->ps_mainproc->p_siglist) == 0) || \
+       (((p)->p_p->ps_flags & PS_TRACED) == 0 && SIGPENDING(p) == 0))  \
+           ? 0 : issignal(p))
 
 /*
  * Clear a pending signal from a process.