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



The following reply was made to PR kern/36183; it has been noted by GNATS.

From: Nick Hudson <nick.hudson%gmx.co.uk@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: 
Subject: Re: kern/36183: problem with ptrace and multithreaded processes
Date: Sat, 15 Nov 2008 12:23:15 +0000

 --Boundary-00=_z8rHJdryVpSZsGt
 Content-Type: text/plain;
   charset="us-ascii"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline
 
 Here's a workaround patch from ad
 
 --Boundary-00=_z8rHJdryVpSZsGt
 Content-Type: text/x-diff;
   charset="us-ascii";
   name="pr36183.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
        filename="pr36183.diff"
 
 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 */
  
 
 --Boundary-00=_z8rHJdryVpSZsGt--
 


Home | Main Index | Thread Index | Old Index