Page MenuHomeFreeBSD

D26416.id77083.diff
No OneTemporary

D26416.id77083.diff

Index: sys/kern/kern_exit.c
===================================================================
--- sys/kern/kern_exit.c
+++ sys/kern/kern_exit.c
@@ -104,7 +104,7 @@
sx_assert(&proctree_lock, SX_LOCKED);
if ((child->p_treeflag & P_TREE_ORPHANED) == 0)
return (child->p_pptr->p_pid == child->p_oppid ?
- child->p_pptr : initproc);
+ child->p_pptr : child->p_reaper);
for (p = child; (p->p_treeflag & P_TREE_FIRST_ORPHAN) == 0;) {
/* Cannot use LIST_PREV(), since the list head is not known. */
p = __containerof(p->p_orphan.le_prev, struct proc,
Index: sys/kern/kern_proc.c
===================================================================
--- sys/kern/kern_proc.c
+++ sys/kern/kern_proc.c
@@ -645,6 +645,35 @@
q->p_pgrp->pg_session == pgrp->pg_session);
}
+static struct proc *
+jobc_reaper(struct proc *p)
+{
+ struct proc *pp;
+
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ for (pp = p;;) {
+ pp = pp->p_reaper;
+ if (pp->p_reaper == pp ||
+ (pp->p_treeflag & P_TREE_GRPEXITED) == 0)
+ return (pp);
+ }
+}
+
+static struct proc *
+jobc_parent(struct proc *p)
+{
+ struct proc *pp;
+
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ pp = proc_realparent(p);
+ if (pp->p_pptr == NULL ||
+ (pp->p_treeflag & P_TREE_GRPEXITED) == 0)
+ return (pp);
+ return (jobc_reaper(pp));
+}
+
#ifdef INVARIANTS
static void
check_pgrp_jobc(struct pgrp *pgrp)
@@ -661,7 +690,7 @@
if ((q->p_treeflag & P_TREE_GRPEXITED) != 0 ||
q->p_pptr == NULL)
continue;
- if (isjobproc(q->p_pptr, pgrp))
+ if (isjobproc(jobc_parent(q), pgrp))
cnt++;
}
KASSERT(pgrp->pg_jobc == cnt, ("pgrp %d %p pg_jobc %d cnt %d",
@@ -784,6 +813,25 @@
PGRP_UNLOCK(pgrp);
}
+static void
+fixjobc_enterpgrp_q(struct pgrp *pgrp, struct proc *p, struct proc *q, bool adj)
+{
+ struct pgrp *childpgrp;
+ bool future_jobc;
+
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ if ((q->p_treeflag & P_TREE_GRPEXITED) != 0)
+ return;
+ childpgrp = q->p_pgrp;
+ future_jobc = childpgrp != pgrp &&
+ childpgrp->pg_session == pgrp->pg_session;
+
+ if ((adj && !isjobproc(p, childpgrp) && future_jobc) ||
+ (!adj && isjobproc(p, childpgrp) && !future_jobc))
+ pgadjustjobc(childpgrp, adj);
+}
+
/*
* Adjust pgrp jobc counters when specified process changes process group.
* We count the number of processes in each process group that "qualify"
@@ -798,8 +846,6 @@
fixjobc_enterpgrp(struct proc *p, struct pgrp *pgrp)
{
struct proc *q;
- struct pgrp *childpgrp;
- bool future_jobc;
sx_assert(&proctree_lock, SX_LOCKED);
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
@@ -809,55 +855,70 @@
if (p->p_pgrp == pgrp)
return;
- if (isjobproc(p->p_pptr, pgrp))
+ if (isjobproc(jobc_parent(p), pgrp))
pgadjustjobc(pgrp, true);
LIST_FOREACH(q, &p->p_children, p_sibling) {
- if ((q->p_treeflag & P_TREE_GRPEXITED) != 0)
+ if ((q->p_treeflag & P_TREE_ORPHANED) != 0)
continue;
- childpgrp = q->p_pgrp;
- future_jobc = childpgrp != pgrp &&
- childpgrp->pg_session == pgrp->pg_session;
- if (!isjobproc(p, childpgrp) && future_jobc)
- pgadjustjobc(childpgrp, true);
+ fixjobc_enterpgrp_q(pgrp, p, q, true);
}
+ LIST_FOREACH(q, &p->p_orphans, p_orphan)
+ fixjobc_enterpgrp_q(pgrp, p, q, true);
- if (isjobproc(p->p_pptr, p->p_pgrp))
+ if (isjobproc(jobc_parent(p), p->p_pgrp))
pgadjustjobc(p->p_pgrp, false);
LIST_FOREACH(q, &p->p_children, p_sibling) {
- if ((q->p_treeflag & P_TREE_GRPEXITED) != 0)
+ if ((q->p_treeflag & P_TREE_ORPHANED) != 0)
continue;
- childpgrp = q->p_pgrp;
- future_jobc = childpgrp != pgrp &&
- childpgrp->pg_session == pgrp->pg_session;
- if (isjobproc(p, childpgrp) && !future_jobc)
- pgadjustjobc(childpgrp, false);
+ fixjobc_enterpgrp_q(pgrp, p, q, false);
}
+ LIST_FOREACH(q, &p->p_orphans, p_orphan)
+ fixjobc_enterpgrp_q(pgrp, p, q, false);
+}
+
+static void
+fixjobc_kill_q(struct proc *p, struct proc *q, bool adj)
+{
+ struct pgrp *childpgrp;
+
+ sx_assert(&proctree_lock, SX_LOCKED);
+
+ if ((q->p_treeflag & P_TREE_GRPEXITED) != 0)
+ return;
+ childpgrp = q->p_pgrp;
+
+ if ((adj && isjobproc(jobc_reaper(q), childpgrp) &&
+ !isjobproc(p, childpgrp)) || (!adj && !isjobproc(jobc_reaper(q),
+ childpgrp) && isjobproc(p, childpgrp)))
+ pgadjustjobc(childpgrp, adj);
}
static void
fixjobc_kill(struct proc *p)
{
struct proc *q;
- struct pgrp *childpgrp, *pgrp;
+ struct pgrp *pgrp;
sx_assert(&proctree_lock, SX_LOCKED);
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
pgrp = p->p_pgrp;
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
+ check_pgrp_jobc(pgrp);
/*
* p no longer affects process group orphanage for children.
* It is marked by the flag because p is only physically
* removed from its process group on wait(2).
*/
+ MPASS((p->p_treeflag & P_TREE_GRPEXITED) == 0);
p->p_treeflag |= P_TREE_GRPEXITED;
/*
* Check p's parent to see whether p qualifies its own process
* group; if so, adjust count for p's process group.
*/
- if (isjobproc(p->p_pptr, pgrp))
+ if (isjobproc(jobc_parent(p), pgrp))
pgadjustjobc(pgrp, false);
/*
@@ -866,21 +927,21 @@
* adjust counts for children's process groups.
*/
LIST_FOREACH(q, &p->p_children, p_sibling) {
- if ((q->p_treeflag & P_TREE_GRPEXITED) != 0)
+ if ((q->p_treeflag & P_TREE_ORPHANED) != 0)
continue;
- childpgrp = q->p_pgrp;
- if (isjobproc(q->p_reaper, childpgrp) &&
- !isjobproc(p, childpgrp))
- pgadjustjobc(childpgrp, true);
+ fixjobc_kill_q(p, q, true);
}
+ LIST_FOREACH(q, &p->p_orphans, p_orphan)
+ fixjobc_kill_q(p, q, true);
LIST_FOREACH(q, &p->p_children, p_sibling) {
- if ((q->p_treeflag & P_TREE_GRPEXITED) != 0)
+ if ((q->p_treeflag & P_TREE_ORPHANED) != 0)
continue;
- childpgrp = q->p_pgrp;
- if (!isjobproc(q->p_reaper, childpgrp) &&
- isjobproc(p, childpgrp))
- pgadjustjobc(childpgrp, false);
+ fixjobc_kill_q(p, q, false);
}
+ LIST_FOREACH(q, &p->p_orphans, p_orphan)
+ fixjobc_kill_q(p, q, false);
+
+ check_pgrp_jobc(pgrp);
}
void
@@ -995,6 +1056,16 @@
#ifdef DDB
+static void
+db_print_pgrp_one(struct pgrp *pgrp, struct proc *p)
+{
+ db_printf(
+ " pid %d at %p pr %d pgrp %p e %d jc %d\n",
+ p->p_pid, p, p->p_pptr == NULL ? -1 : p->p_pptr->p_pid,
+ p->p_pgrp, (p->p_treeflag & P_TREE_GRPEXITED) != 0,
+ p->p_pptr == NULL ? 0 : isjobproc(p->p_pptr, pgrp));
+}
+
DB_SHOW_COMMAND(pgrpdump, pgrpdump)
{
struct pgrp *pgrp;
@@ -1003,19 +1074,15 @@
for (i = 0; i <= pgrphash; i++) {
if (!LIST_EMPTY(&pgrphashtbl[i])) {
- printf("\tindx %d\n", i);
+ db_printf("indx %d\n", i);
LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) {
- printf(
- "\tpgrp %p, pgid %ld, sess %p, sesscnt %d, mem %p\n",
- (void *)pgrp, (long)pgrp->pg_id,
- (void *)pgrp->pg_session,
+ db_printf(
+ " pgrp %p, pgid %d, sess %p, sesscnt %d, mem %p\n",
+ pgrp, (int)pgrp->pg_id, pgrp->pg_session,
pgrp->pg_session->s_count,
- (void *)LIST_FIRST(&pgrp->pg_members));
- LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
- printf("\t\tpid %ld addr %p pgrp %p\n",
- (long)p->p_pid, (void *)p,
- (void *)p->p_pgrp);
- }
+ LIST_FIRST(&pgrp->pg_members));
+ LIST_FOREACH(p, &pgrp->pg_members, p_pglist)
+ db_print_pgrp_one(pgrp, p);
}
}
}

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 21, 1:19 PM (11 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16011680
Default Alt Text
D26416.id77083.diff (7 KB)

Event Timeline