svn commit: r325777 - head/sys/kern
John Baldwin
jhb at FreeBSD.org
Mon Nov 13 21:09:10 UTC 2017
Author: jhb
Date: Mon Nov 13 21:09:08 2017
New Revision: 325777
URL: https://svnweb.freebsd.org/changeset/base/325777
Log:
Pull the PT_ATTACH case out of the 'sendsig:' block.
Most of the conditionals in the 'sendsig:' block are now only different
for PT_ATTACH vs other continue requests. Pull the PT_ATTACH-specific
logic up into the PT_ATTACH case and simplify the 'sendsig:' block. This
also permits moving the unlock of proctree_lock above the sendsig: label
since PT_KILL doesn't hold the lock and and the other cases all fall
through to the label.
Reviewed by: kib
Differential Revision: https://reviews.freebsd.org/D13073
Modified:
head/sys/kern/sys_process.c
Modified: head/sys/kern/sys_process.c
==============================================================================
--- head/sys/kern/sys_process.c Mon Nov 13 20:49:08 2017 (r325776)
+++ head/sys/kern/sys_process.c Mon Nov 13 21:09:08 2017 (r325777)
@@ -920,11 +920,28 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi
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 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi
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 @@ kern_ptrace(struct thread *td, int req, pid_t pid, voi
*
* 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:
More information about the svn-src-head
mailing list