svn commit: r287605 - in stable/9/sys: fs/procfs kern
John Baldwin
jhb at FreeBSD.org
Wed Sep 9 23:41:26 UTC 2015
Author: jhb
Date: Wed Sep 9 23:41:24 2015
New Revision: 287605
URL: https://svnweb.freebsd.org/changeset/base/287605
Log:
MFC 283281,283282,283562,286158:
Various fixes to orphan handling which also fix issues with following
forks. Unlike the changes in HEAD, this merge does not include the
changes to the ATF ptrace test since ATF is not present in 9.
283281:
Always set p_oppid when attaching to an existing process via procfs
tracing. This matches the behavior of ptrace(PT_ATTACH). Also,
the procfs detach request assumes p_oppid is always set.
283282:
Only reparent a traced process to its old parent if the tracing process is
not the old parent. Otherwise, proc_reap() will leave the zombie in place
resulting in the process' status being returned twice to its parent.
283562:
Do not allow a process to reap an orphan (a child currently being
traced by another process such as a debugger). The parent process does
need to check for matching orphan pids to avoid returning ECHILD if an
orphan has exited, but it should not return the exited status for the
child until after the debugger has detached from the orphan process
either explicitly or implicitly via wait().
286158:
Clear P_TRACED before reparenting a detached process back to its
original parent. Otherwise the debugee will be set as an orphan of
the debugger.
Modified:
stable/9/sys/fs/procfs/procfs_ctl.c
stable/9/sys/kern/kern_exit.c
stable/9/sys/kern/sys_process.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/fs/ (props changed)
Modified: stable/9/sys/fs/procfs/procfs_ctl.c
==============================================================================
--- stable/9/sys/fs/procfs/procfs_ctl.c Wed Sep 9 23:39:30 2015 (r287604)
+++ stable/9/sys/fs/procfs/procfs_ctl.c Wed Sep 9 23:41:24 2015 (r287605)
@@ -143,8 +143,8 @@ procfs_control(struct thread *td, struct
p->p_flag |= P_TRACED;
faultin(p);
p->p_xstat = 0; /* XXX ? */
+ p->p_oppid = p->p_pptr->p_pid;
if (p->p_pptr != td->td_proc) {
- p->p_oppid = p->p_pptr->p_pid;
proc_reparent(p, td->td_proc);
}
kern_psignal(p, SIGSTOP);
Modified: stable/9/sys/kern/kern_exit.c
==============================================================================
--- stable/9/sys/kern/kern_exit.c Wed Sep 9 23:39:30 2015 (r287604)
+++ stable/9/sys/kern/kern_exit.c Wed Sep 9 23:41:24 2015 (r287605)
@@ -825,13 +825,13 @@ proc_reap(struct thread *td, struct proc
PROC_LOCK(q);
sigqueue_take(p->p_ksi);
PROC_UNLOCK(q);
- PROC_UNLOCK(p);
/*
* If we got the child via a ptrace 'attach', we need to give it back
* to the old parent.
*/
- if (p->p_oppid != 0) {
+ if (p->p_oppid != 0 && p->p_oppid != p->p_pptr->p_pid) {
+ PROC_UNLOCK(p);
t = proc_realparent(p);
PROC_LOCK(t);
PROC_LOCK(p);
@@ -848,6 +848,8 @@ proc_reap(struct thread *td, struct proc
sx_xunlock(&proctree_lock);
return;
}
+ p->p_oppid = 0;
+ PROC_UNLOCK(p);
/*
* Remove other references to this process to ensure we have an
@@ -926,7 +928,8 @@ proc_reap(struct thread *td, struct proc
static int
proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id,
- int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo)
+ int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo,
+ int check_only)
{
struct proc *q;
struct rusage *rup;
@@ -1065,7 +1068,7 @@ proc_to_reap(struct thread *td, struct p
calccru(p, &rup->ru_utime, &rup->ru_stime);
}
- if (p->p_state == PRS_ZOMBIE) {
+ if (p->p_state == PRS_ZOMBIE && !check_only) {
proc_reap(td, p, status, options);
return (-1);
}
@@ -1159,7 +1162,7 @@ loop:
sx_xlock(&proctree_lock);
LIST_FOREACH(p, &q->p_children, p_sibling) {
ret = proc_to_reap(td, p, idtype, id, status, options,
- wrusage, siginfo);
+ wrusage, siginfo, 0);
if (ret == 0)
continue;
else if (ret == 1)
@@ -1261,15 +1264,17 @@ loop:
* for. By maintaining a list of orphans we allow the parent
* to successfully wait until the child becomes a zombie.
*/
- LIST_FOREACH(p, &q->p_orphans, p_orphan) {
- ret = proc_to_reap(td, p, idtype, id, status, options,
- wrusage, siginfo);
- if (ret == 0)
- continue;
- else if (ret == 1)
- nfound++;
- else
- return (0);
+ if (nfound == 0) {
+ LIST_FOREACH(p, &q->p_orphans, p_orphan) {
+ ret = proc_to_reap(td, p, idtype, id, NULL, options,
+ NULL, NULL, 1);
+ if (ret != 0) {
+ KASSERT(ret != -1, ("reaped an orphan (pid %d)",
+ (int)td->td_retval[0]));
+ nfound++;
+ break;
+ }
+ }
}
if (nfound == 0) {
sx_xunlock(&proctree_lock);
Modified: stable/9/sys/kern/sys_process.c
==============================================================================
--- stable/9/sys/kern/sys_process.c Wed Sep 9 23:39:30 2015 (r287604)
+++ stable/9/sys/kern/sys_process.c Wed Sep 9 23:41:24 2015 (r287605)
@@ -949,7 +949,15 @@ kern_ptrace(struct thread *td, int req,
}
break;
case PT_DETACH:
- /* reset process parent */
+ /*
+ * Reset the process parent.
+ *
+ * NB: This clears P_TRACED before reparenting
+ * a detached process back to its original
+ * parent. Otherwise the debugee will be set
+ * as an orphan of the debugger.
+ */
+ p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
if (p->p_oppid != p->p_pptr->p_pid) {
PROC_LOCK(p->p_pptr);
sigqueue_take(p->p_ksi);
@@ -965,7 +973,6 @@ kern_ptrace(struct thread *td, int req,
} else
CTR1(KTR_PTRACE, "PT_DETACH: pid %d", p->p_pid);
p->p_oppid = 0;
- p->p_flag &= ~(P_TRACED | P_WAITED | P_FOLLOWFORK);
/* should we send SIGCHLD? */
/* childproc_continued(p); */
More information about the svn-src-stable-9
mailing list