NetBSD-Bugs archive

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

Re: kern/36183: problem with ptrace and multithreaded processes



Here's a workaround patch from ad
Index: sys/kern/kern_sig.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_sig.c,v
retrieving revision 1.289
diff -u -p -u -r1.289 kern_sig.c
--- sys/kern/kern_sig.c 24 Oct 2008 18:07:36 -0000      1.289
+++ sys/kern/kern_sig.c 15 Nov 2008 10:57:48 -0000
@@ -1653,9 +1653,9 @@ sigswitch(bool ppsig, int ppmask, int si
         */
        KERNEL_UNLOCK_ALL(l, &biglocks);
        if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) {
+               KASSERT(l->l_stat == LSONPROC);
                p->p_nrlwps--;
                lwp_lock(l);
-               KASSERT(l->l_stat == LSONPROC || l->l_stat == LSSLEEP);
                l->l_stat = LSSTOP;
                lwp_unlock(l);
        }
@@ -1684,19 +1684,25 @@ sigchecktrace(sigpend_t **spp)
         * If we are no longer being traced, or the parent didn't
         * give us a signal, look for more signals.
         */
-       if ((p->p_slflag & PSL_TRACED) == 0 || p->p_xstat == 0)
+       if ((p->p_slflag & PSL_TRACED) == 0 ||
+           p->p_xstat == 0 || p->p_xlwp != l)
                return 0;
 
-       /* If there's a pending SIGKILL, process it immediately. */
-       if (sigismember(&p->p_sigpend.sp_set, SIGKILL))
+       /*
+        * If there's a pending SIGKILL or the process is on the way
+        * out, process immediately.
+        */
+       if (sigismember(&p->p_sigpend.sp_set, SIGKILL) ||
+           (l->l_flag & (LW_WCORE | LW_WEXIT)) != 0)
                return 0;
 
        /*
-        * If the new signal is being masked, look for other signals.
-        * `p->p_sigctx.ps_siglist |= mask' is done in setrunnable().
+        * sigaddset() is done in setrunnable().
         */
        signo = p->p_xstat;
+       *spp = &l->l_sigpend;
        p->p_xstat = 0;
+       p->p_xlwp = NULL;
        if ((sigprop[signo] & SA_TOLWP) != 0)
                *spp = &l->l_sigpend;
        else
@@ -1956,11 +1962,24 @@ postsig(int signo)
        }
 
        /*
+        * If the process is exiting or dumping core (possible after the
+        * unlock above), then bail out now.  Both of these conditions
+        * will be visible with only the proc mutex held.  Note that the
+        * call to lwp_userret() is recursive, but we will not come back
+        * this way.
+        */
+       if ((l->l_flag & (LW_WEXIT | LW_WCORE)) != 0) {
+               lwp_userret(l);
+               panic("postsig userret");
+               /* NOTREACHED */
+       }
+
+       /*
         * If we get here, the signal must be caught.
         */
 #ifdef DIAGNOSTIC
        if (action == SIG_IGN || sigismember(&l->l_sigmask, signo))
-               panic("postsig action");
+               panic("postsig: action");
 #endif
 
        kpsendsig(l, &ksi, returnmask);
@@ -2261,6 +2280,7 @@ proc_unstop(struct proc *p)
 
        p->p_stat = SACTIVE;
        p->p_sflag &= ~PS_STOPPING;
+       p->p_xlwp = NULL;
        sig = p->p_xstat;
 
        if (!p->p_waited)
@@ -2276,15 +2296,21 @@ proc_unstop(struct proc *p)
                        setrunnable(l);
                        continue;
                }
-               if (sig && (l->l_flag & LW_SINTR) != 0) {
-                       setrunnable(l);
+               if (sig && (l->l_flag & LW_SINTR) != 0 &&
+                   !sigismember(&l->l_sigmask, sig)) {
                        sig = 0;
+                       setrunnable(l);
                } else {
                        l->l_stat = LSSLEEP;
                        p->p_nrlwps++;
                        lwp_unlock(l);
                }
        }
+
+       if (p->p_xlwp == NULL) {
+               /* No LWP available to take the signal. */
+               p->p_xstat = 0;
+       }
 }
 
 static int
Index: sys/kern/kern_synch.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_synch.c,v
retrieving revision 1.255
diff -u -p -u -r1.255 kern_synch.c
--- sys/kern/kern_synch.c       15 Nov 2008 10:54:32 -0000      1.255
+++ sys/kern/kern_synch.c       15 Nov 2008 10:57:49 -0000
@@ -925,7 +925,6 @@ setrunnable(struct lwp *l)
 {
        struct proc *p = l->l_proc;
        struct cpu_info *ci;
-       sigset_t *ss;
 
        KASSERT((l->l_flag & LW_IDLE) == 0);
        KASSERT(mutex_owned(p->p_lock));
@@ -938,13 +937,12 @@ setrunnable(struct lwp *l)
                 * If we're being traced (possibly because someone attached us
                 * while we were stopped), check for a signal from the debugger.
                 */
-               if ((p->p_slflag & PSL_TRACED) != 0 && p->p_xstat != 0) {
-                       if ((sigprop[p->p_xstat] & SA_TOLWP) != 0)
-                               ss = &l->l_sigpend.sp_set;
-                       else
-                               ss = &p->p_sigpend.sp_set;
-                       sigaddset(ss, p->p_xstat);
+               if ((p->p_slflag & PSL_TRACED) != 0 && p->p_xstat != 0 &&
+                   p->p_xlwp == NULL &&
+                   !sigismember(&l->l_sigmask, p->p_xstat)) {
+                       sigaddset(&l->l_sigpend.sp_set, p->p_xstat);
                        signotify(l);
+                       p->p_xlwp = l;
                }
                p->p_nrlwps++;
                break;
Index: sys/sys/proc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/proc.h,v
retrieving revision 1.282
diff -u -p -u -r1.282 proc.h
--- sys/sys/proc.h      22 Oct 2008 11:14:33 -0000      1.282
+++ sys/sys/proc.h      15 Nov 2008 10:57:49 -0000
@@ -290,6 +290,7 @@ struct proc {
        LIST_HEAD(, lwp) p_sigwaiters;  /* p: LWPs waiting for signals */
        sigstore_t      p_sigstore;     /* p: process-wide signal state */
        sigpend_t       p_sigpend;      /* p: pending signals */
+       struct lwp      *p_xlwp;        /* s: LWP to take sig from debugger */
        struct lcproc   *p_lwpctl;      /* p, a: _lwp_ctl() information */
        pid_t           p_ppid;         /* :: cached parent pid */
 


Home | Main Index | Thread Index | Old Index