The branch stable/13 has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=4f88de7e09e7a1370aebd0a7ef64b3e8134c0cd3

commit 4f88de7e09e7a1370aebd0a7ef64b3e8134c0cd3
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2021-06-05 12:42:27 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2021-06-22 01:45:31 +0000

    Add a knob to not drop signal with default ignored or ignored actions
    
    (cherry picked from commit bc38762474caed2d41d2562e28f56aa211f47ceb)
---
 sys/kern/kern_sig.c | 65 +++++++++++++++++++++++++++++++----------------------
 sys/sys/proc.h      |  1 +
 sys/sys/sysent.h    |  1 +
 3 files changed, 40 insertions(+), 27 deletions(-)

diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 1cab25aa5a40..4f6f424fb05d 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -163,6 +163,12 @@ SYSCTL_BOOL(_kern, OID_AUTO, sigfastblock_fetch_always, 
CTLFLAG_RWTUN,
     "Fetch sigfastblock word on each syscall entry for proper "
     "blocking semantic");
 
+static bool    kern_sig_discard_ign = true;
+SYSCTL_BOOL(_kern, OID_AUTO, sig_discard_ign, CTLFLAG_RWTUN,
+    &kern_sig_discard_ign, 0,
+    "Discard ignored signals on delivery, otherwise queue them to "
+    "the target queue");
+
 SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL);
 
 /*
@@ -1290,6 +1296,9 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, 
ksiginfo_t *ksi,
        PROC_LOCK(p);
        saved_mask = td->td_sigmask;
        SIGSETNAND(td->td_sigmask, waitset);
+       if ((p->p_sysent->sv_flags & SV_SIG_DISCIGN) != 0 ||
+           !kern_sig_discard_ign)
+               td->td_pflags2 |= TDP2_SIGWAIT;
        for (;;) {
                mtx_lock(&ps->ps_mtx);
                sig = cursig(td);
@@ -1352,6 +1361,7 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, 
ksiginfo_t *ksi,
                if (error == 0 && (p->p_ptevents & PTRACE_SYSCALL) != 0)
                        traced = true;
        }
+       td->td_pflags2 &= ~TDP2_SIGWAIT;
 
        new_block = saved_mask;
        SIGSETNAND(new_block, td->td_sigmask);
@@ -2200,22 +2210,25 @@ tdsendsignal(struct proc *p, struct thread *td, int 
sig, ksiginfo_t *ksi)
        SDT_PROBE3(proc, , , signal__send, td, p, sig);
 
        /*
-        * If the signal is being ignored,
-        * then we forget about it immediately.
-        * (Note: we don't set SIGCONT in ps_sigignore,
-        * and if it is set to SIG_IGN,
-        * action will be SIG_DFL here.)
+        * If the signal is being ignored, then we forget about it
+        * immediately, except when the target process executes
+        * sigwait().  (Note: we don't set SIGCONT in ps_sigignore,
+        * and if it is set to SIG_IGN, action will be SIG_DFL here.)
         */
        mtx_lock(&ps->ps_mtx);
        if (SIGISMEMBER(ps->ps_sigignore, sig)) {
-               SDT_PROBE3(proc, , , signal__discard, td, p, sig);
+               if (kern_sig_discard_ign &&
+                   (p->p_sysent->sv_flags & SV_SIG_DISCIGN) == 0) {
+                       SDT_PROBE3(proc, , , signal__discard, td, p, sig);
 
-               mtx_unlock(&ps->ps_mtx);
-               if (ksi && (ksi->ksi_flags & KSI_INS))
-                       ksiginfo_tryfree(ksi);
-               return (ret);
-       }
-       if (SIGISMEMBER(td->td_sigmask, sig))
+                       mtx_unlock(&ps->ps_mtx);
+                       if (ksi && (ksi->ksi_flags & KSI_INS))
+                               ksiginfo_tryfree(ksi);
+                       return (ret);
+               } else {
+                       action = SIG_CATCH;
+               }
+       } else if (SIGISMEMBER(td->td_sigmask, sig))
                action = SIG_HOLD;
        else if (SIGISMEMBER(ps->ps_sigcatch, sig))
                action = SIG_CATCH;
@@ -2950,11 +2963,13 @@ issignal(struct thread *td)
                }
 
                /*
-                * We should see pending but ignored signals
-                * only if P_TRACED was on when they were posted.
+                * We should allow pending but ignored signals below
+                * only if there is sigwait() active, or P_TRACED was
+                * on when they were posted.
                 */
                if (SIGISMEMBER(ps->ps_sigignore, sig) &&
-                   (p->p_flag & P_TRACED) == 0) {
+                   (p->p_flag & P_TRACED) == 0 &&
+                   (td->td_pflags2 & TDP2_SIGWAIT) == 0) {
                        sigqueue_delete(&td->td_sigqueue, sig);
                        sigqueue_delete(&p->p_sigqueue, sig);
                        continue;
@@ -3066,10 +3081,11 @@ issignal(struct thread *td)
                                PROC_SUNLOCK(p);
                                mtx_lock(&ps->ps_mtx);
                                goto next;
-                       } else if (prop & SIGPROP_IGNORE) {
+                       } else if ((prop & SIGPROP_IGNORE) != 0 &&
+                           (td->td_pflags2 & TDP2_SIGWAIT) == 0) {
                                /*
-                                * Except for SIGCONT, shouldn't get here.
-                                * Default action is to ignore; drop it.
+                                * Default action is to ignore; drop it if
+                                * not in kern_sigtimedwait().
                                 */
                                break;          /* == ignore */
                        } else
@@ -3077,15 +3093,10 @@ issignal(struct thread *td)
                        /*NOTREACHED*/
 
                case (intptr_t)SIG_IGN:
-                       /*
-                        * Masking above should prevent us ever trying
-                        * to take action on an ignored signal other
-                        * than SIGCONT, unless process is traced.
-                        */
-                       if ((prop & SIGPROP_CONT) == 0 &&
-                           (p->p_flag & P_TRACED) == 0)
-                               printf("issignal\n");
-                       break;          /* == ignore */
+                       if ((td->td_pflags2 & TDP2_SIGWAIT) == 0)
+                               break;          /* == ignore */
+                       else
+                               return (sig);
 
                default:
                        /*
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index d4476ac8d410..373e62bd266d 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -529,6 +529,7 @@ do {                                                        
                \
 #define        TDP2_SBPAGES    0x00000001 /* Owns sbusy on some pages */
 #define        TDP2_COMPAT32RB 0x00000002 /* compat32 ABI for robust lists */
 #define        TDP2_ACCT       0x00000004 /* Doing accounting */
+#define        TDP2_SIGWAIT    0x00000008 /* Ignore ignored signals */
 
 /*
  * Reasons that the current thread can not be run yet.
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index c2cbd77a92b9..95e9dcb1a335 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -161,6 +161,7 @@ struct sysentvec {
 #define        SV_TIMEKEEP     0x040000        /* Shared page timehands. */
 #define        SV_ASLR         0x080000        /* ASLR allowed. */
 #define        SV_RNG_SEED_VER 0x100000        /* random(4) reseed generation. 
*/
+#define        SV_SIG_DISCIGN  0x200000        /* Do not discard ignored 
signals */
 
 #define        SV_ABI_MASK     0xff
 #define        SV_PROC_FLAG(p, x)      ((p)->p_sysent->sv_flags & (x))
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to