Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -1081,7 +1081,7 @@ proc_reparent(p, dbg); sx_xunlock(&proctree_lock); td->td_dbgflags |= TDB_CHILD | TDB_SCX | TDB_FSTP; - ptracestop(td, SIGSTOP); + ptracestop(td, SIGSTOP, NULL); td->td_dbgflags &= ~(TDB_CHILD | TDB_SCX); } else { /* @@ -1102,7 +1102,7 @@ _STOPEVENT(p, S_SCX, td->td_dbg_sc_code); if ((p->p_ptevents & PTRACE_SCX) != 0 || (td->td_dbgflags & TDB_BORN) != 0) - ptracestop(td, SIGTRAP); + ptracestop(td, SIGTRAP, NULL); td->td_dbgflags &= ~(TDB_SCX | TDB_BORN); PROC_UNLOCK(p); } Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -2500,10 +2500,11 @@ return (wakeup_swapper); } -int -ptracestop(struct thread *td, int sig) +void +ptracestop(struct thread *td, int sig, int *newsig) { struct proc *p = td->td_proc; + ksiginfo_t ksi; PROC_LOCK_ASSERT(p, MA_OWNED); KASSERT(!(p->p_flag & P_WEXIT), ("Stopping exiting process")); @@ -2523,8 +2524,8 @@ * events when the process exits. */ td->td_dbgflags &= ~TDB_XSIG; - PROC_SUNLOCK(p); - return (sig); + td->td_xsig = sig; + break; } /* @@ -2563,7 +2564,18 @@ } } PROC_SUNLOCK(p); - return (td->td_xsig); + if (newsig) + *newsig = td->td_xsig; + else if (td->td_xsig) { + /* + * Caller is not prepared to deliver a debugger requested + * signal. We must queue it up for handling next ast. + */ + ksiginfo_init(&ksi); + ksi.ksi_flags |= KSI_HEAD; + ksi.ksi_signo = td->td_xsig; + tdksignal(td, td->td_xsig, &ksi); + } } static void @@ -2783,7 +2795,16 @@ } mtx_unlock(&ps->ps_mtx); - newsig = ptracestop(td, sig); + if (td->td_xsig) + /* + * This signal is from a previous call to + * ptracestop() that was unable to deliver + * it. + */ + newsig = td->td_xsig; + else + ptracestop(td, sig, &newsig); + td->td_xsig = 0; mtx_lock(&ps->ps_mtx); if (sig != newsig) { Index: sys/kern/kern_thr.c =================================================================== --- sys/kern/kern_thr.c +++ sys/kern/kern_thr.c @@ -356,7 +356,7 @@ p->p_pendingexits++; td->td_dbgflags |= TDB_EXIT; if (p->p_ptevents & PTRACE_LWP) - ptracestop(td, SIGTRAP); + ptracestop(td, SIGTRAP, NULL); PROC_UNLOCK(p); tidhash_remove(td); PROC_LOCK(p); Index: sys/kern/subr_syscall.c =================================================================== --- sys/kern/subr_syscall.c +++ sys/kern/subr_syscall.c @@ -88,7 +88,7 @@ td->td_dbg_sc_code = sa->code; td->td_dbg_sc_narg = sa->narg; if (p->p_ptevents & PTRACE_SCE) - ptracestop((td), SIGTRAP); + ptracestop((td), SIGTRAP, NULL); PROC_UNLOCK(p); } if (td->td_dbgflags & TDB_USERWR) { @@ -222,7 +222,7 @@ if (traced && ((td->td_dbgflags & (TDB_FORK | TDB_EXEC)) != 0 || (p->p_ptevents & PTRACE_SCX) != 0)) - ptracestop(td, SIGTRAP); + ptracestop(td, SIGTRAP, NULL); td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK); PROC_UNLOCK(p); } @@ -259,7 +259,7 @@ if (td->td_dbgflags & TDB_VFORK) { PROC_LOCK(p); if (p->p_ptevents & PTRACE_VFORK) - ptracestop(td, SIGTRAP); + ptracestop(td, SIGTRAP, NULL); td->td_dbgflags &= ~TDB_VFORK; PROC_UNLOCK(p); } Index: sys/sys/signalvar.h =================================================================== --- sys/sys/signalvar.h +++ sys/sys/signalvar.h @@ -370,7 +370,7 @@ void pgsignal(struct pgrp *pgrp, int sig, int checkctty, ksiginfo_t *ksi); int postsig(int sig); void kern_psignal(struct proc *p, int sig); -int ptracestop(struct thread *td, int sig); +void ptracestop(struct thread *td, int sig, int *newsig); void sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *retmask); struct sigacts *sigacts_alloc(void); void sigacts_copy(struct sigacts *dest, struct sigacts *src);