Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163505209
D58264.id182338.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D58264.id182338.diff
View Options
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -720,6 +720,20 @@
}
} else
PROC_LOCK(p->p_pptr);
+ if ((p->p_treeflag & P_TREE_ORPHANED) != 0) {
+ /*
+ * Process is orphaned. Add PZOMBIEREF_ORPHAN zombie
+ * reference if real parent created the process with
+ * fork() and not pdfork(). Also wake up the real
+ * parent, so it can collect the exit status and clear
+ * its zombie reference.
+ */
+ nq = proc_realparent(p);
+ MPASS(p->p_pptr != nq);
+ if ((p->p_zombieref & PZOMBIEREF_PARENT) != 0)
+ p->p_zombieref |= PZOMBIEREF_ORPHAN;
+ wakeup(nq);
+ }
sx_xunlock(&proctree_lock);
if (signal_parent == 1) {
@@ -982,13 +996,17 @@
* lock as part of its work.
*/
void
-proc_reap(struct thread *td, struct proc *p, int *status, int options)
+proc_reap(struct thread *td, struct proc *p, int *status, int options,
+ int zombieref)
{
struct proc *q, *t;
sx_assert(&proctree_lock, SA_XLOCKED);
PROC_LOCK_ASSERT(p, MA_OWNED);
KASSERT(p->p_state == PRS_ZOMBIE, ("proc_reap: !PRS_ZOMBIE"));
+ MPASS(zombieref == PZOMBIEREF_PARENT ||
+ zombieref == PZOMBIEREF_PROCDESC ||
+ zombieref == PZOMBIEREF_ORPHAN);
mtx_spin_wait_unlocked(&p->p_slock);
@@ -1006,6 +1024,13 @@
return;
}
+ p->p_zombieref &= ~zombieref;
+ if (p->p_zombieref != 0) {
+ PROC_UNLOCK(p);
+ sx_xunlock(&proctree_lock);
+ return;
+ }
+
PROC_LOCK(q);
sigqueue_take(p->p_ksi);
PROC_UNLOCK(q);
@@ -1179,7 +1204,7 @@
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,
- bool check_only)
+ int zombieref)
{
sx_assert(&proctree_lock, SA_XLOCKED);
@@ -1187,9 +1212,8 @@
switch (idtype) {
case P_ALL:
- if (p->p_procdesc == NULL ||
- (p->p_pptr == td->td_proc &&
- (p->p_flag & P_TRACED) != 0)) {
+ if ((p->p_zombieref & zombieref) != 0 ||
+ (p->p_pptr == td->td_proc && (p->p_flag & P_TRACED) != 0)) {
break;
}
@@ -1241,12 +1265,9 @@
return (0);
}
- if (p_canwait(td, p)) {
- PROC_UNLOCK(p);
- return (0);
- }
-
- if ((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) {
+ if (p_canwait(td, p) != 0 ||
+ ((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) ||
+ (p->p_zombieref & zombieref) == 0) {
PROC_UNLOCK(p);
return (0);
}
@@ -1274,8 +1295,8 @@
*/
wait_fill_wrusage(p, wrusage);
- if (p->p_state == PRS_ZOMBIE && !check_only) {
- proc_reap(td, p, status, options);
+ if (p->p_state == PRS_ZOMBIE) {
+ proc_reap(td, p, status, options, zombieref);
return (-1);
}
return (1);
@@ -1468,7 +1489,7 @@
LIST_FOREACH(p, &q->p_children, p_sibling) {
pid = p->p_pid;
ret = proc_to_reap(td, p, idtype, id, status, options,
- wrusage, siginfo, false);
+ wrusage, siginfo, PZOMBIEREF_PARENT);
if (ret == 0)
continue;
else if (ret != 1) {
@@ -1476,18 +1497,6 @@
return (0);
}
- /*
- * When running in capsicum(4) mode, make wait(2) ignore
- * processes created with pdfork(2). This is because one can
- * disown them - by passing their process descriptor to another
- * process - which means it needs to be prevented from touching
- * them afterwards.
- */
- if (IN_CAPABILITY_MODE(td) && p->p_procdesc != NULL) {
- PROC_UNLOCK(p);
- continue;
- }
-
nfound++;
PROC_LOCK_ASSERT(p, MA_OWNED);
@@ -1514,13 +1523,14 @@
if (nfound == 0) {
LIST_FOREACH(p, &q->p_orphans, p_orphan) {
ret = proc_to_reap(td, p, idtype, id, NULL, options,
- NULL, NULL, true);
+ NULL, NULL, PZOMBIEREF_ORPHAN);
if (ret != 0) {
KASSERT(ret != -1, ("reaped an orphan (pid %d)",
(int)td->td_retval[0]));
PROC_UNLOCK(p);
- nfound++;
- break;
+ td->td_retval[0] = p->p_pid;
+ sx_xunlock(&proctree_lock);
+ return (0);
}
}
}
@@ -1583,7 +1593,8 @@
error = p_canwait(td, p);
if (error != 0)
break;
- if ((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) {
+ if (((options & WEXITED) == 0 && p->p_state == PRS_ZOMBIE) ||
+ (p->p_zombieref & PZOMBIEREF_PROCDESC) == 0) {
error = ESRCH;
break;
}
@@ -1592,7 +1603,7 @@
wait_fill_wrusage(p, wrusage);
if (p->p_state == PRS_ZOMBIE) {
- proc_reap(td, p, status, options);
+ proc_reap(td, p, status, options, PZOMBIEREF_PROCDESC);
goto exit_unlocked;
}
@@ -1665,6 +1676,16 @@
child->p_pptr = parent;
if (set_oppid)
child->p_oppid = parent->p_pid;
+
+ /*
+ * When reparenting the child to the reaper, re-enable
+ * waitpid(2) for it, so that the zombie can be collected.
+ */
+ if ((child->p_flag & P_TRACED) == 0 && child->p_reaper == parent &&
+ (child->p_zombieref & PZOMBIEREF_PARENT) == 0) {
+ child->p_zombieref |= PZOMBIEREF_PARENT;
+ child->p_zombieref &= ~PZOMBIEREF_ORPHAN;
+ }
}
static void
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -547,6 +547,8 @@
P2_STKGAP_DISABLE | P2_STKGAP_DISABLE_EXEC | P2_NO_NEW_PRIVS |
P2_WXORX_DISABLE | P2_WXORX_ENABLE_EXEC | P2_LOGSIGEXIT_CTL |
P2_LOGSIGEXIT_ENABLE);
+ p2->p_zombieref = (fr->fr_flags & RFPROCDESC) != 0 ?
+ PZOMBIEREF_PROCDESC : PZOMBIEREF_PARENT;
p2->p_swtick = ticks;
if (p1->p_flag & P_PROFIL)
startprofclock(p2);
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -307,6 +307,7 @@
PROCDESC_UNLOCK(pd);
pd->pd_proc = NULL;
p->p_procdesc = NULL;
+ p->p_zombieref &= ~PZOMBIEREF_PROCDESC;
procdesc_free(pd);
return (true);
}
@@ -316,7 +317,8 @@
/* Wakeup all waiters for this procdesc' process exit. */
wakeup(&p->p_procdesc);
- return (false);
+ return ((p->p_zombieref & (PZOMBIEREF_PARENT |
+ PZOMBIEREF_ORPHAN)) != 0);
}
void
@@ -418,7 +420,7 @@
* process's reference to the process descriptor when it
* calls back into procdesc_reap().
*/
- proc_reap(curthread, p, NULL, 0);
+ proc_reap(curthread, p, NULL, 0, PZOMBIEREF_PROCDESC);
} else if (pd->pd_fpcount == 0) /* last procdesc */ {
/*
* If the process is not yet dead, we need to kill it,
@@ -429,11 +431,16 @@
*/
pd->pd_proc = NULL;
p->p_procdesc = NULL;
+ p->p_zombieref &= ~PZOMBIEREF_PROCDESC;
pd->pd_pid = -1;
procdesc_free(pd);
- /* Failed finstall() should not cause reaping. */
- if ((fp->f_pdflags & F_PD_NOFINSTALL) == 0) {
+ /*
+ * A reference for waitpid() or failed
+ * finstall() should not cause reaping.
+ */
+ if ((fp->f_pdflags & F_PD_NOFINSTALL) == 0 ||
+ (p->p_zombieref & PZOMBIEREF_PARENT) == 0) {
/*
* Next, reparent it to its reaper
* (usually init(8)) so that there's
@@ -642,6 +649,7 @@
}
pd = p->p_procdesc;
if (pd != NULL) {
+ MPASS((p->p_zombieref & PZOMBIEREF_PROCDESC) != 0);
refcount_acquire(&pd->pd_refcount);
PROCDESC_LOCK(pd);
MPASS(pd->pd_fpcount > 0);
@@ -653,6 +661,8 @@
pd->pd_proc = p;
pd->pd_pid = p->p_pid;
p->p_procdesc = pd;
+ MPASS((p->p_zombieref & PZOMBIEREF_PROCDESC) == 0);
+ p->p_zombieref |= PZOMBIEREF_PROCDESC;
}
procdesc_finit(pd, fp);
PROC_UNLOCK(p);
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -782,6 +782,7 @@
LIST_ENTRY(proc) p_jaillist; /* (d) Jail process linkage. */
u_int p_asig; /* (c) ASYNCEXIT pending signal. */
u_int p_tree_refcnt; /* (e) proctree refcount */
+ u_int p_zombieref; /* (e + c) References for reap. */
};
#define p_session p_pgrp->pg_session
@@ -911,6 +912,11 @@
#define P_TREE_REAPER 0x00000004 /* Reaper of subtree */
#define P_TREE_GRPEXITED 0x00000008 /* exit1() done with job ctl */
+/* p_zombieref; protected both by proctree_lock and process mutex. */
+#define PZOMBIEREF_PARENT 0x00000001 /* Ref for waitpid() */
+#define PZOMBIEREF_PROCDESC 0x00000002 /* Ref for pdwait() */
+#define PZOMBIEREF_ORPHAN 0x00000004 /* Ref for waitpid() on orphan */
+
/*
* These were process status values (p_stat), now they are only used in
* legacy conversion code.
@@ -1205,7 +1211,8 @@
void proc_linkup0(struct proc *p, struct thread *td);
void proc_linkup(struct proc *p, struct thread *td);
struct proc *proc_realparent(struct proc *child);
-void proc_reap(struct thread *td, struct proc *p, int *status, int options);
+void proc_reap(struct thread *td, struct proc *p, int *status, int options,
+ int zombieref);
void proc_reparent(struct proc *child, struct proc *newparent, bool set_oppid);
void proc_set_p2_wexit(struct proc *p);
void proc_set_traced(struct proc *p, bool stop);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jul 24, 10:03 PM (15 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35454223
Default Alt Text
D58264.id182338.diff (8 KB)
Attached To
Mode
D58264: processes: add zombie references, each of them prevents reap
Attached
Detach File
Event Timeline
Log In to Comment