Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_sig.c
Show First 20 Lines • Show All 2,495 Lines • ▼ Show 20 Lines | WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, | ||||
&p->p_mtx.lock_object, "Stopping for traced signal"); | &p->p_mtx.lock_object, "Stopping for traced signal"); | ||||
td->td_dbgflags |= TDB_XSIG; | td->td_dbgflags |= TDB_XSIG; | ||||
td->td_xsig = sig; | td->td_xsig = sig; | ||||
CTR4(KTR_PTRACE, "ptracestop: tid %d (pid %d) flags %#x sig %d", | CTR4(KTR_PTRACE, "ptracestop: tid %d (pid %d) flags %#x sig %d", | ||||
td->td_tid, p->p_pid, td->td_dbgflags, sig); | td->td_tid, p->p_pid, td->td_dbgflags, sig); | ||||
PROC_SLOCK(p); | PROC_SLOCK(p); | ||||
while ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_XSIG)) { | while ((p->p_flag & P_TRACED) && (td->td_dbgflags & TDB_XSIG)) { | ||||
if (p->p_flag & P_SINGLE_EXIT) { | if (p->p_flag & P_SINGLE_EXIT && | ||||
!(td->td_dbgflags & TDB_EXIT)) { | |||||
/* | |||||
* Ignore ptrace stops except for thread exit | |||||
* events when the process exits. | |||||
*/ | |||||
td->td_dbgflags &= ~TDB_XSIG; | td->td_dbgflags &= ~TDB_XSIG; | ||||
PROC_SUNLOCK(p); | PROC_SUNLOCK(p); | ||||
return (sig); | return (sig); | ||||
} | } | ||||
/* | /* | ||||
* Just make wait() to work, the last stopped thread | * Just make wait() to work, the last stopped thread | ||||
* will win. | * will win. | ||||
*/ | */ | ||||
Show All 13 Lines | if (!(p->p_flag & P_TRACED)) | ||||
break; | break; | ||||
if (td->td_dbgflags & TDB_SUSPEND) { | if (td->td_dbgflags & TDB_SUSPEND) { | ||||
if (p->p_flag & P_SINGLE_EXIT) | if (p->p_flag & P_SINGLE_EXIT) | ||||
break; | break; | ||||
goto stopme; | goto stopme; | ||||
} | } | ||||
} | } | ||||
PROC_SUNLOCK(p); | PROC_SUNLOCK(p); | ||||
/* XXX: Clear TDB_XSIG in case P_TRACED was never set? */ | |||||
jhb: So this was more of a question in that should we always clear TDB_XSIG here? In particular… | |||||
kibUnsubmitted Not Done Inline ActionsLeaked TDB_XSIG indeed might cause spurious report of PL_EVENT_SIGNAL, so I agree that clearing it would fix this. But, note the if (!P_TRACED) break; and if (P_SINGLE_EXIT) break; cases after stopme. I am not sure if it could be useful someday to see that thread was terminated while debug event was pending. Might be, do not set TDB_XSIG and return early from ptracestop() if P_TRACED is not set ? May be not, and just clear it at the end for now. I think both variants are fine. kib: Leaked TDB_XSIG indeed might cause spurious report of PL_EVENT_SIGNAL, so I agree that clearing… | |||||
return (td->td_xsig); | return (td->td_xsig); | ||||
} | } | ||||
static void | static void | ||||
reschedule_signals(struct proc *p, sigset_t block, int flags) | reschedule_signals(struct proc *p, sigset_t block, int flags) | ||||
{ | { | ||||
struct sigacts *ps; | struct sigacts *ps; | ||||
struct thread *td; | struct thread *td; | ||||
▲ Show 20 Lines • Show All 1,034 Lines • Show Last 20 Lines |
So this was more of a question in that should we always clear TDB_XSIG here? In particular, syscall traps do not check P_TRACED under the PROC_LOCK, so it might be cleared in between when it was checked and when the thread acquires the lock before entering ptracestop(). In that case the loop would never be entered and this function would return with TDB_XSIG still set. I will go ahead and commit the LWP events without this comment, but I think a followup commit to always clear TDB_XSIG here might be warranted? (Either that or check for P_TRACED again under the PROC_LOCK in the system call traps?)