Index: head/sys/kern/sys_process.c =================================================================== --- head/sys/kern/sys_process.c +++ head/sys/kern/sys_process.c @@ -920,11 +920,28 @@ if (p->p_pptr != td->td_proc) { proc_reparent(p, td->td_proc); } - data = SIGSTOP; CTR2(KTR_PTRACE, "PT_ATTACH: pid %d, oppid %d", p->p_pid, p->p_oppid); - goto sendsig; /* in PT_CONTINUE below */ + sx_xunlock(&proctree_lock); + proctree_locked = 0; + MPASS(p->p_xthread == NULL); + MPASS((p->p_flag & P_STOPPED_TRACE) == 0); + + /* + * If already stopped due to a stop signal, clear the + * existing stop before triggering a traced SIGSTOP. + */ + if ((p->p_flag & P_STOPPED_SIG) != 0) { + PROC_SLOCK(p); + p->p_flag &= ~(P_STOPPED_SIG | P_WAITED); + thread_unsuspend(p); + PROC_SUNLOCK(p); + } + + kern_psignal(p, SIGSTOP); + break; + case PT_CLEARSTEP: CTR2(KTR_PTRACE, "PT_CLEARSTEP: tid %d (pid %d)", td2->td_tid, p->p_pid); @@ -1123,12 +1140,11 @@ break; } + sx_xunlock(&proctree_lock); + proctree_locked = 0; + sendsig: - /* proctree_locked is true for all but PT_KILL. */ - if (proctree_locked) { - sx_xunlock(&proctree_lock); - proctree_locked = 0; - } + MPASS(proctree_locked == 0); /* * Clear the pending event for the thread that just @@ -1138,54 +1154,36 @@ * * Deliver any pending signal via the reporting thread. */ - if ((p->p_flag & P_STOPPED_TRACE) != 0) { - MPASS(p->p_xthread != NULL); - p->p_xthread->td_dbgflags &= ~TDB_XSIG; - p->p_xthread->td_xsig = data; - p->p_xthread = NULL; - p->p_xsig = data; - } else { - MPASS(p->p_xthread == NULL); - MPASS(req == PT_ATTACH); - } + MPASS(p->p_xthread != NULL); + p->p_xthread->td_dbgflags &= ~TDB_XSIG; + p->p_xthread->td_xsig = data; + p->p_xthread = NULL; + p->p_xsig = data; - if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) != 0) { - /* - * P_WKILLED is insurance that a PT_KILL/SIGKILL always - * works immediately, even if another thread is - * unsuspended first and attempts to handle a different - * signal or if the POSIX.1b style signal queue cannot - * accommodate any new signals. - */ - if (data == SIGKILL) - p->p_flag |= P_WKILLED; + /* + * P_WKILLED is insurance that a PT_KILL/SIGKILL + * always works immediately, even if another thread is + * unsuspended first and attempts to handle a + * different signal or if the POSIX.1b style signal + * queue cannot accommodate any new signals. + */ + if (data == SIGKILL) + p->p_flag |= P_WKILLED; - if (req == PT_DETACH) { - FOREACH_THREAD_IN_PROC(p, td3) - td3->td_dbgflags &= ~TDB_SUSPEND; - } - - /* - * Unsuspend all threads. To leave a thread - * suspended, use PT_SUSPEND to suspend it - * before continuing the process. - */ - PROC_SLOCK(p); - p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED); - thread_unsuspend(p); - PROC_SUNLOCK(p); + if (req == PT_DETACH) { + FOREACH_THREAD_IN_PROC(p, td3) + td3->td_dbgflags &= ~TDB_SUSPEND; } /* - * For requests other than PT_ATTACH, P_STOPPED_TRACE - * was set, so any pending signal in 'data' is - * delivered via the reporting thread (p_xthread). - * For PT_ATTACH the process is not yet stopped for - * tracing, so P_STOPPED_TRACE cannot be set and the - * SIGSTOP must be delivered to the process. + * Unsuspend all threads. To leave a thread + * suspended, use PT_SUSPEND to suspend it before + * continuing the process. */ - if (req == PT_ATTACH) - kern_psignal(p, data); + PROC_SLOCK(p); + p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED); + thread_unsuspend(p); + PROC_SUNLOCK(p); break; case PT_WRITE_I: