152 lines
4 KiB
Diff
152 lines
4 KiB
Diff
--- sys/kern/sys_process.c.orig
|
|
+++ sys/kern/sys_process.c
|
|
@@ -869,7 +869,7 @@
|
|
}
|
|
|
|
/* not currently stopped */
|
|
- if ((p->p_flag & (P_STOPPED_SIG | P_STOPPED_TRACE)) == 0 ||
|
|
+ if ((p->p_flag & P_STOPPED_TRACE) == 0 ||
|
|
p->p_suspcount != p->p_numthreads ||
|
|
(p->p_flag & P_WAITED) == 0) {
|
|
error = EBUSY;
|
|
@@ -876,12 +876,6 @@
|
|
goto fail;
|
|
}
|
|
|
|
- if ((p->p_flag & P_STOPPED_TRACE) == 0) {
|
|
- static int count = 0;
|
|
- if (count++ == 0)
|
|
- printf("P_STOPPED_TRACE not set.\n");
|
|
- }
|
|
-
|
|
/* OK */
|
|
break;
|
|
}
|
|
@@ -926,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);
|
|
@@ -1117,8 +1128,10 @@
|
|
sigqueue_delete(&td3->td_sigqueue,
|
|
SIGSTOP);
|
|
}
|
|
- td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP);
|
|
+ td3->td_dbgflags &= ~(TDB_XSIG | TDB_FSTP |
|
|
+ TDB_SUSPEND);
|
|
}
|
|
+
|
|
if ((p->p_flag2 & P2_PTRACE_FSTP) != 0) {
|
|
sigqueue_delete(&p->p_sigqueue, SIGSTOP);
|
|
p->p_flag2 &= ~P2_PTRACE_FSTP;
|
|
@@ -1129,54 +1142,45 @@
|
|
break;
|
|
}
|
|
|
|
+ sx_xunlock(&proctree_lock);
|
|
+ proctree_locked = 0;
|
|
+
|
|
sendsig:
|
|
- /*
|
|
+ MPASS(proctree_locked == 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 any pending signal via the reporting thread.
|
|
*/
|
|
- td2 = p->p_xthread;
|
|
- if (proctree_locked) {
|
|
- sx_xunlock(&proctree_lock);
|
|
- proctree_locked = 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;
|
|
- 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;
|
|
|
|
- /*
|
|
- * 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 not let a thread run,
|
|
- * you should use PT_SUSPEND to suspend it before
|
|
- * continuing process.
|
|
- */
|
|
- PROC_SLOCK(p);
|
|
- p->p_flag &= ~(P_STOPPED_TRACE|P_STOPPED_SIG|P_WAITED);
|
|
- thread_unsuspend(p);
|
|
- PROC_SUNLOCK(p);
|
|
- if (req == PT_ATTACH)
|
|
- kern_psignal(p, data);
|
|
- } else {
|
|
- if (data)
|
|
- kern_psignal(p, data);
|
|
- }
|
|
+ /*
|
|
+ * 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);
|
|
break;
|
|
|
|
case PT_WRITE_I:
|