Index: sys/kern/sys_process.c =================================================================== --- sys/kern/sys_process.c +++ sys/kern/sys_process.c @@ -1129,24 +1129,35 @@ } sendsig: - /* - * Clear the pending event for the thread that just - * reported its event (p_xthread). This may not be - * the thread passed to PT_CONTINUE, PT_STEP, etc. if - * the debugger is resuming a different thread. - */ - td2 = p->p_xthread; + /* proctree_locked is true for all but PT_KILL. */ if (proctree_locked) { sx_xunlock(&proctree_lock); proctree_locked = 0; } + p->p_xsig = data; - p->p_xthread = NULL; if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) != 0) { - /* deliver or queue signal */ - td2->td_dbgflags &= ~TDB_XSIG; - td2->td_xsig = data; + if ((p->p_flag & P_STOPPED_TRACE) != 0) { + /* + * Clear the pending event for the + * thread that just reported its event + * (p_xthread). This may not be the + * thread passed to PT_CONTINUE, + * PT_STEP, etc. if the debugger is + * resuming a different thread. + * + * Deliver the pending signal via the + * reporting thread in this case rather + * than the process. + */ + MPASS(p->p_xthread != NULL); + p->p_xthread->td_dbgflags &= ~TDB_XSIG; + p->p_xthread->td_xsig = data; + p->p_xthread = NULL; + } + /* Can p_xsig assignment be moved here? */ + /* * P_WKILLED is insurance that a PT_KILL/SIGKILL always * works immediately, even if another thread is @@ -1161,21 +1172,41 @@ FOREACH_THREAD_IN_PROC(p, td3) td3->td_dbgflags &= ~TDB_SUSPEND; } + /* - * unsuspend all threads, to not let a thread run, - * you should use PT_SUSPEND to suspend it before - * continuing process. + * 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); + + /* + * XXX: Should this instead be + * if (orig_p_xthread == NULL) to + * handle PT_KILL when p_xthread is not set but + * P_STOPPED_SIG is set? Can that even happen? + * One can only PT_KILL a traced process, and a + * traced process should not have P_STOPPED_SIGNAL + * set and not also have P_STOPPED_TRACE, so perhaps + * req == PT_ATTACH is sufficient? + */ if (req == PT_ATTACH) kern_psignal(p, data); } else { + /* + * XXX: Isn't this always true? All but + * PT_ATTACH require P_STOPPED_SIG or + * P_STOPPED_TRACE, and PT_ATTACH hardcodes + * data to SIGTOP. + */ + MPASS(data != 0); if (data) kern_psignal(p, data); } + MPASS(p->p_xthread == NULL); break; case PT_WRITE_I: