From 2dccc7280a7f218019b80a7a0b65f5cb51973cda Mon Sep 17 00:00:00 2001 From: Mike Karels Date: Sat, 1 Dec 1990 22:27:04 -0800 Subject: [PATCH] fix jobc adjustments so we increment before decrementing, avoiding spurious signals when we join parent's pgrp; move common code into subr (from torek) SCCS-vsn: sys/kern/kern_proc.c 7.12 SCCS-vsn: sys/kern/kern_exit.c 7.28 --- usr/src/sys/kern/kern_exit.c | 4 +- usr/src/sys/kern/kern_proc.c | 132 +++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 62 deletions(-) diff --git a/usr/src/sys/kern/kern_exit.c b/usr/src/sys/kern/kern_exit.c index 84b93f8c8a..351e3e0675 100644 --- a/usr/src/sys/kern/kern_exit.c +++ b/usr/src/sys/kern/kern_exit.c @@ -4,7 +4,7 @@ * * %sccs.include.redist.c% * - * @(#)kern_exit.c 7.27 (Berkeley) %G% + * @(#)kern_exit.c 7.28 (Berkeley) %G% */ #include "param.h" @@ -180,7 +180,7 @@ done: ruadd(p->p_ru, &u.u_cru); if (p->p_cptr) /* only need this if any child is S_ZOMB */ wakeup((caddr_t)&proc[1]); - fixjobc(p, 0); + fixjobc(p, p->p_pgrp, 0); for (q = p->p_cptr; q != NULL; q = nq) { nq = q->p_osptr; if (nq != NULL) diff --git a/usr/src/sys/kern/kern_proc.c b/usr/src/sys/kern/kern_proc.c index 6e2d406059..db1412f6b7 100644 --- a/usr/src/sys/kern/kern_proc.c +++ b/usr/src/sys/kern/kern_proc.c @@ -4,7 +4,7 @@ * * %sccs.include.redist.c% * - * @(#)kern_proc.c 7.11 (Berkeley) %G% + * @(#)kern_proc.c 7.12 (Berkeley) %G% */ #include "param.h" @@ -37,6 +37,7 @@ inferior(p) register struct proc *p; { + for (; p != u.u_procp; p = p->p_pptr) if (p->p_ppid == 0) return (0); @@ -81,10 +82,9 @@ pgmv(p, pgid, mksess) pid_t pgid; { register struct pgrp *pgrp = pgfind(pgid); - register struct proc **pp = &p->p_pgrp->pg_mem; + register struct proc **pp; register struct proc *cp; - struct pgrp *opgrp; - register n; + int n; #ifdef DIAGNOSTIC if (pgrp && mksess) /* firewalls */ @@ -124,42 +124,42 @@ pgmv(p, pgid, mksess) pgrp->pg_session->s_count++; } pgrp->pg_id = pgid; - pgrp->pg_hforw = pgrphash[n=PIDHASH(pgid)]; + pgrp->pg_hforw = pgrphash[n = PIDHASH(pgid)]; pgrphash[n] = pgrp; pgrp->pg_jobc = 0; pgrp->pg_mem = NULL; } else if (pgrp == p->p_pgrp) return; + /* - * adjust eligibility of affected pgrps to participate in job control + * Adjust eligibility of affected pgrps to participate in job control. + * Increment eligibility counts before decrementing, otherwise we + * could reach 0 spuriously during the first call. */ - fixjobc(p, 0); + fixjobc(p, pgrp, 1); + fixjobc(p, p->p_pgrp, 0); + /* * unlink p from old process group */ - for (; *pp; pp = &(*pp)->p_pgrpnxt) + for (pp = &p->p_pgrp->pg_mem; *pp; pp = &(*pp)->p_pgrpnxt) if (*pp == p) { *pp = p->p_pgrpnxt; goto done; } panic("pgmv: can't find p on old pgrp"); done: + /* + * delete old if empty + */ + if (p->p_pgrp->pg_mem == 0) + pgdelete(p->p_pgrp); /* * link into new one */ + p->p_pgrp = pgrp; p->p_pgrpnxt = pgrp->pg_mem; pgrp->pg_mem = p; - opgrp = p->p_pgrp; - p->p_pgrp = pgrp; - /* - * adjust eligibility of affected pgrps to participate in job control - */ - fixjobc(p, 1); - /* - * delete old if empty - */ - if (!opgrp->pg_mem) - pgdelete(opgrp); } /* @@ -206,59 +206,71 @@ done: } /* - * Adjust pgrp jobc counter. - * flag == 0 => p is leaving current state. - * flag == 1 => p is entering current state. + * Adjust pgrp jobc counters when specified process changes process group. + * We count the number of processes in each process group that "qualify" + * the group for terminal job control (those with a parent in a different + * process group of the same session). If that count reaches zero, the + * process group becomes orphaned. Check both the specified process' + * process group and that of its children. + * entering == 0 => p is leaving specified group. + * entering == 1 => p is entering specified group. */ -fixjobc(p, flag) +fixjobc(p, pgrp, entering) register struct proc *p; - register flag; + register struct pgrp *pgrp; + int entering; { - register struct pgrp *mypgrp = p->p_pgrp, *hispgrp; - register struct session *mysession = mypgrp->pg_session; - register struct proc *qp; + register struct pgrp *hispgrp; + register struct session *mysession = pgrp->pg_session; - if ((hispgrp = p->p_pptr->p_pgrp) != mypgrp && + /* + * Check p's parent to see whether p qualifies its own process + * group; if so, adjust count for p's process group. + */ + if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && hispgrp->pg_session == mysession) - if (flag) - mypgrp->pg_jobc++; - else if (--mypgrp->pg_jobc == 0) { - int deliver = 0; - - sigstopped: - for (qp = mypgrp->pg_mem; qp != NULL; - qp = qp->p_pgrpnxt) - if (deliver) { - psignal(qp, SIGHUP); - psignal(qp, SIGCONT); - } else if (qp->p_stat == SSTOP) { - deliver++; - goto sigstopped; - } - } + if (entering) + pgrp->pg_jobc++; + else if (--pgrp->pg_jobc == 0) + orphanpg(pgrp); - for (p = p->p_cptr; p != NULL; p = p->p_osptr) - if ((hispgrp = p->p_pgrp) != mypgrp && + /* + * Check this process' children to see whether they qualify + * their process groups; if so, adjust counts for children's + * process groups. + */ + for (p = p->p_cptr; p; p = p->p_osptr) + if ((hispgrp = p->p_pgrp) != pgrp && hispgrp->pg_session == mysession && p->p_stat != SZOMB) - if (flag) + if (entering) hispgrp->pg_jobc++; - else if (--hispgrp->pg_jobc == 0) { - int deliver = 0; + else if (--hispgrp->pg_jobc == 0) + orphanpg(hispgrp); +} - sigstopped2: - for (qp = hispgrp->pg_mem; qp != NULL; - qp = qp->p_pgrpnxt) - if (deliver) { - psignal(qp, SIGHUP); - psignal(qp, SIGCONT); - } else if (qp->p_stat == SSTOP) { - deliver++; - goto sigstopped2; - } +/* + * A process group has become orphaned; + * if there are any stopped processes in the group, + * hang-up all process in that group. + */ +static +orphanpg(pg) + struct pgrp *pg; +{ + register struct proc *p; + + for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { + if (p->p_stat == SSTOP) { + for (p = pg->pg_mem; p; p = p->p_pgrpnxt) { + psignal(p, SIGHUP); + psignal(p, SIGCONT); } + return; + } + } } - + /* * init the process queues */ -- 2.20.1