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