Page MenuHomeFreeBSD

D27871.1778538006.diff
No OneTemporary

Size
20 KB
Referenced Files
None
Subscribers
None

D27871.1778538006.diff

diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -2386,8 +2386,10 @@
KASSERT(*sizep == size, ("invalid size"));
structsize = sizeof(elf_kinfo_proc_t);
sbuf_bcat(sb, &structsize, sizeof(structsize));
+ sx_slock(&proctree_lock);
PROC_LOCK(p);
kern_proc_out(p, sb, ELF_KERN_PROC_MASK);
+ sx_sunlock(&proctree_lock);
}
*sizep = size;
}
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -98,20 +98,18 @@
SDT_PROVIDER_DEFINE(proc);
-MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
MALLOC_DEFINE(M_SESSION, "session", "session header");
static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
-static void fixjobc_enterpgrp(struct proc *p, struct pgrp *pgrp);
static void doenterpgrp(struct proc *, struct pgrp *);
static void orphanpg(struct pgrp *pg);
static void fill_kinfo_aggregate(struct proc *p, struct kinfo_proc *kp);
static void fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp);
static void fill_kinfo_thread(struct thread *td, struct kinfo_proc *kp,
int preferthread);
-static void pgadjustjobc(struct pgrp *pgrp, bool entering);
static void pgdelete(struct pgrp *);
+static int pgrp_init(void *mem, int size, int flags);
static int proc_ctor(void *mem, int size, void *arg, int flags);
static void proc_dtor(void *mem, int size, void *arg);
static int proc_init(void *mem, int size, int flags);
@@ -133,6 +131,7 @@
struct mtx __exclusive_cache_line ppeers_lock;
struct mtx __exclusive_cache_line procid_lock;
uma_zone_t proc_zone;
+uma_zone_t pgrp_zone;
/*
* The offset of various fields in struct proc and struct thread.
@@ -196,6 +195,8 @@
proc_zone = uma_zcreate("PROC", sched_sizeof_proc(),
proc_ctor, proc_dtor, proc_init, proc_fini,
UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ pgrp_zone = uma_zcreate("PGRP", sizeof(struct pgrp), NULL, NULL,
+ pgrp_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
uihashinit();
}
@@ -299,6 +300,16 @@
#endif
}
+static int
+pgrp_init(void *mem, int size, int flags)
+{
+ struct pgrp *pg;
+
+ pg = mem;
+ mtx_init(&pg->pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK);
+ return (0);
+}
+
/*
* PID space management.
*
@@ -570,8 +581,6 @@
KASSERT(!SESS_LEADER(p),
("enterpgrp: session leader attempted setpgrp"));
- mtx_init(&pgrp->pg_mtx, "process group", NULL, MTX_DEF | MTX_DUPOK);
-
if (sess != NULL) {
/*
* new session
@@ -601,13 +610,13 @@
pgrp->pg_id = pgid;
proc_id_set(PROC_ID_GROUP, p->p_pid);
LIST_INIT(&pgrp->pg_members);
+ pgrp->pg_flags = 0;
/*
* As we have an exclusive lock of proctree_lock,
* this should not deadlock.
*/
LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
- pgrp->pg_jobc = 0;
SLIST_INIT(&pgrp->pg_sigiolst);
PGRP_UNLOCK(pgrp);
@@ -629,12 +638,10 @@
PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
KASSERT(pgrp->pg_session == p->p_session,
- ("%s: pgrp's session %p, p->p_session %p.\n",
- __func__,
- pgrp->pg_session,
- p->p_session));
+ ("%s: pgrp's session %p, p->p_session %p proc %p\n",
+ __func__, pgrp->pg_session, p->p_session, p));
KASSERT(pgrp != p->p_pgrp,
- ("%s: p belongs to pgrp.", __func__));
+ ("%s: p %p belongs to pgrp %p", __func__, p, pgrp));
doenterpgrp(p, pgrp);
@@ -649,6 +656,7 @@
isjobproc(struct proc *q, struct pgrp *pgrp)
{
sx_assert(&proctree_lock, SX_LOCKED);
+
return (q->p_pgrp != pgrp &&
q->p_pgrp->pg_session == pgrp->pg_session);
}
@@ -658,7 +666,7 @@
{
struct proc *pp;
- sx_assert(&proctree_lock, SX_LOCKED);
+ sx_assert(&proctree_lock, SA_LOCKED);
for (pp = p;;) {
pp = pp->p_reaper;
@@ -669,43 +677,40 @@
}
static struct proc *
-jobc_parent(struct proc *p)
+jobc_parent(struct proc *p, struct proc *p_exiting)
{
struct proc *pp;
- sx_assert(&proctree_lock, SX_LOCKED);
+ sx_assert(&proctree_lock, SA_LOCKED);
pp = proc_realparent(p);
- if (pp->p_pptr == NULL ||
+ if (pp->p_pptr == NULL || pp == p_exiting ||
(pp->p_treeflag & P_TREE_GRPEXITED) == 0)
return (pp);
return (jobc_reaper(pp));
}
-#ifdef INVARIANTS
-static void
-check_pgrp_jobc(struct pgrp *pgrp)
+static int
+pgrp_calc_jobc(struct pgrp *pgrp)
{
struct proc *q;
int cnt;
- sx_assert(&proctree_lock, SX_LOCKED);
- PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
+#ifdef INVARIANTS
+ if (!mtx_owned(&pgrp->pg_mtx))
+ sx_assert(&proctree_lock, SA_LOCKED);
+#endif
cnt = 0;
- PGRP_LOCK(pgrp);
LIST_FOREACH(q, &pgrp->pg_members, p_pglist) {
if ((q->p_treeflag & P_TREE_GRPEXITED) != 0 ||
q->p_pptr == NULL)
continue;
- if (isjobproc(jobc_parent(q), pgrp))
+ if (isjobproc(jobc_parent(q, NULL), pgrp))
cnt++;
}
- KASSERT(pgrp->pg_jobc == cnt, ("pgrp %d %p pg_jobc %d cnt %d",
- pgrp->pg_id, pgrp, pgrp->pg_jobc, cnt));
- PGRP_UNLOCK(pgrp);
+ return (cnt);
}
-#endif
/*
* Move p to a process group
@@ -714,6 +719,7 @@
doenterpgrp(struct proc *p, struct pgrp *pgrp)
{
struct pgrp *savepgrp;
+ struct proc *pp;
sx_assert(&proctree_lock, SX_XLOCKED);
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
@@ -722,24 +728,19 @@
SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
savepgrp = p->p_pgrp;
-
-#ifdef INVARIANTS
- check_pgrp_jobc(pgrp);
- check_pgrp_jobc(savepgrp);
-#endif
-
- /*
- * Adjust eligibility of affected pgrps to participate in job control.
- */
- fixjobc_enterpgrp(p, pgrp);
+ pp = jobc_parent(p, NULL);
PGRP_LOCK(pgrp);
PGRP_LOCK(savepgrp);
+ if (isjobproc(pp, savepgrp) && pgrp_calc_jobc(savepgrp) == 1)
+ orphanpg(savepgrp);
PROC_LOCK(p);
LIST_REMOVE(p, p_pglist);
p->p_pgrp = pgrp;
PROC_UNLOCK(p);
LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
+ if (isjobproc(pp, pgrp))
+ pgrp->pg_flags &= ~PGRP_ORPHANED;
PGRP_UNLOCK(savepgrp);
PGRP_UNLOCK(pgrp);
if (LIST_EMPTY(&savepgrp->pg_members))
@@ -800,107 +801,10 @@
}
proc_id_clear(PROC_ID_GROUP, pgrp->pg_id);
- mtx_destroy(&pgrp->pg_mtx);
- free(pgrp, M_PGRP);
+ uma_zfree(pgrp_zone, pgrp);
sess_release(savesess);
}
-static void
-pgadjustjobc(struct pgrp *pgrp, bool entering)
-{
-
- PGRP_LOCK(pgrp);
- if (entering) {
- MPASS(pgrp->pg_jobc >= 0);
- pgrp->pg_jobc++;
- } else {
- MPASS(pgrp->pg_jobc > 0);
- --pgrp->pg_jobc;
- if (pgrp->pg_jobc == 0)
- orphanpg(pgrp);
- }
- 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"
- * 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.
- * We increment eligibility counts before decrementing, otherwise we
- * could reach 0 spuriously during the decrement.
- */
-static void
-fixjobc_enterpgrp(struct proc *p, struct pgrp *pgrp)
-{
- struct proc *q;
-
- sx_assert(&proctree_lock, SX_LOCKED);
- PROC_LOCK_ASSERT(p, MA_NOTOWNED);
- PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
- SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
-
- if (p->p_pgrp == pgrp)
- return;
-
- if (isjobproc(jobc_parent(p), pgrp))
- pgadjustjobc(pgrp, true);
- LIST_FOREACH(q, &p->p_children, p_sibling) {
- if ((q->p_treeflag & P_TREE_ORPHANED) != 0)
- continue;
- fixjobc_enterpgrp_q(pgrp, p, q, true);
- }
- LIST_FOREACH(q, &p->p_orphans, p_orphan)
- fixjobc_enterpgrp_q(pgrp, p, q, true);
-
- 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_ORPHANED) != 0)
- continue;
- 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)
@@ -913,9 +817,6 @@
pgrp = p->p_pgrp;
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
-#ifdef INVARIANTS
- check_pgrp_jobc(pgrp);
-#endif
/*
* p no longer affects process group orphanage for children.
@@ -926,35 +827,46 @@
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.
+ * Check if exiting p orphans its own group.
*/
- if (isjobproc(jobc_parent(p), pgrp))
- pgadjustjobc(pgrp, false);
+ pgrp = p->p_pgrp;
+ if (isjobproc(jobc_parent(p, NULL), pgrp)) {
+ PGRP_LOCK(pgrp);
+ if (pgrp_calc_jobc(pgrp) == 0)
+ orphanpg(pgrp);
+ PGRP_UNLOCK(pgrp);
+ }
/*
* Check this process' children to see whether they qualify
- * their process groups after reparenting to reaper. If so,
- * adjust counts for children's process groups.
+ * their process groups after reparenting to reaper.
*/
LIST_FOREACH(q, &p->p_children, p_sibling) {
- if ((q->p_treeflag & P_TREE_ORPHANED) != 0)
- continue;
- fixjobc_kill_q(p, q, true);
+ pgrp = q->p_pgrp;
+ PGRP_LOCK(pgrp);
+ if (pgrp_calc_jobc(pgrp) == 0) {
+ /*
+ * We want to handle exactly the children that
+ * has p as realparent. Then, when calculating
+ * jobc_parent for children, we should ignore
+ * P_TREE_GRPEXITED flag already set on p.
+ */
+ if (jobc_parent(q, p) == p && isjobproc(p, pgrp))
+ orphanpg(pgrp);
+ } else
+ pgrp->pg_flags &= ~PGRP_ORPHANED;
+ PGRP_UNLOCK(pgrp);
}
- 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_ORPHANED) != 0)
- continue;
- fixjobc_kill_q(p, q, false);
+ LIST_FOREACH(q, &p->p_orphans, p_orphan) {
+ pgrp = q->p_pgrp;
+ PGRP_LOCK(pgrp);
+ if (pgrp_calc_jobc(pgrp) == 0) {
+ if (isjobproc(p, pgrp))
+ orphanpg(pgrp);
+ } else
+ pgrp->pg_flags &= ~PGRP_ORPHANED;
+ PGRP_UNLOCK(pgrp);
}
- LIST_FOREACH(q, &p->p_orphans, p_orphan)
- fixjobc_kill_q(p, q, false);
-
-#ifdef INVARIANTS
- check_pgrp_jobc(pgrp);
-#endif
}
void
@@ -1018,8 +930,8 @@
}
/*
- * A process group has become orphaned;
- * if there are any stopped processes in the group,
+ * A process group has become orphaned, mark it as such for signal
+ * delivery code. If there are any stopped processes in the group,
* hang-up all process in that group.
*/
static void
@@ -1029,6 +941,8 @@
PGRP_LOCK_ASSERT(pg, MA_OWNED);
+ pg->pg_flags |= PGRP_ORPHANED;
+
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
PROC_LOCK(p);
if (P_SHOULDSTOP(p) == P_STOPPED_SIG) {
@@ -1125,22 +1039,18 @@
}
/*
- * Clear kinfo_proc and fill in any information that is common
- * to all threads in the process.
+ * Fill in any information that is common to all threads in the process.
* Must be called with the target process locked.
*/
static void
fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
{
struct thread *td0;
- struct tty *tp;
- struct session *sp;
struct ucred *cred;
struct sigacts *ps;
struct timeval boottime;
PROC_LOCK_ASSERT(p, MA_OWNED);
- bzero(kp, sizeof(*kp));
kp->ki_structsize = sizeof(*kp);
kp->ki_paddr = p;
@@ -1233,36 +1143,6 @@
FOREACH_THREAD_IN_PROC(p, td0)
kp->ki_cow += td0->td_cow;
- tp = NULL;
- if (p->p_pgrp) {
- kp->ki_pgid = p->p_pgrp->pg_id;
- kp->ki_jobc = p->p_pgrp->pg_jobc;
- sp = p->p_pgrp->pg_session;
-
- if (sp != NULL) {
- kp->ki_sid = sp->s_sid;
- SESS_LOCK(sp);
- strlcpy(kp->ki_login, sp->s_login,
- sizeof(kp->ki_login));
- if (sp->s_ttyvp)
- kp->ki_kiflag |= KI_CTTY;
- if (SESS_LEADER(p))
- kp->ki_kiflag |= KI_SLEADER;
- /* XXX proctree_lock */
- tp = sp->s_ttyp;
- SESS_UNLOCK(sp);
- }
- }
- if ((p->p_flag & P_CONTROLT) && tp != NULL) {
- kp->ki_tdev = tty_udev(tp);
- kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
- kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
- if (tp->t_session)
- kp->ki_tsid = tp->t_session->s_sid;
- } else {
- kp->ki_tdev = NODEV;
- kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
- }
if (p->p_comm[0] != '\0')
strlcpy(kp->ki_comm, p->p_comm, sizeof(kp->ki_comm));
if (p->p_sysent && p->p_sysent->sv_name != NULL &&
@@ -1279,6 +1159,53 @@
}
}
+/*
+ * Fill job-related process information.
+ */
+static void
+fill_kinfo_proc_pgrp(struct proc *p, struct kinfo_proc *kp)
+{
+ struct tty *tp;
+ struct session *sp;
+ struct pgrp *pgrp;
+
+ sx_assert(&proctree_lock, SA_LOCKED);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ pgrp = p->p_pgrp;
+ if (pgrp == NULL)
+ return;
+
+ kp->ki_pgid = pgrp->pg_id;
+ kp->ki_jobc = pgrp_calc_jobc(pgrp);
+
+ sp = pgrp->pg_session;
+ tp = NULL;
+
+ if (sp != NULL) {
+ kp->ki_sid = sp->s_sid;
+ SESS_LOCK(sp);
+ strlcpy(kp->ki_login, sp->s_login, sizeof(kp->ki_login));
+ if (sp->s_ttyvp)
+ kp->ki_kiflag |= KI_CTTY;
+ if (SESS_LEADER(p))
+ kp->ki_kiflag |= KI_SLEADER;
+ tp = sp->s_ttyp;
+ SESS_UNLOCK(sp);
+ }
+
+ if ((p->p_flag & P_CONTROLT) && tp != NULL) {
+ kp->ki_tdev = tty_udev(tp);
+ kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
+ kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
+ if (tp->t_session)
+ kp->ki_tsid = tp->t_session->s_sid;
+ } else {
+ kp->ki_tdev = NODEV;
+ kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
+ }
+}
+
/*
* Fill in information that is thread specific. Must be called with
* target process locked. If 'preferthread' is set, overwrite certain
@@ -1398,9 +1325,11 @@
void
fill_kinfo_proc(struct proc *p, struct kinfo_proc *kp)
{
-
MPASS(FIRST_THREAD_IN_PROC(p) != NULL);
+ bzero(kp, sizeof(*kp));
+
+ fill_kinfo_proc_pgrp(p,kp);
fill_kinfo_proc_only(p, kp);
fill_kinfo_thread(FIRST_THREAD_IN_PROC(p), kp, 0);
fill_kinfo_aggregate(p, kp);
@@ -1645,6 +1574,7 @@
int error, i, j;
for (i = 0; i < pidhashlock + 1; i++) {
+ sx_slock(&proctree_lock);
sx_slock(&pidhashtbl_lock[i]);
for (j = i; j <= pidhash; j += pidhashlock + 1) {
LIST_FOREACH(p, &pidhashtbl[j], p_hash) {
@@ -1654,11 +1584,13 @@
PROC_LOCK_ASSERT(p, MA_NOTOWNED);
if (error != 0) {
sx_sunlock(&pidhashtbl_lock[i]);
+ sx_sunlock(&proctree_lock);
return (error);
}
}
}
sx_sunlock(&pidhashtbl_lock[i]);
+ sx_sunlock(&proctree_lock);
}
return (0);
}
@@ -1784,9 +1716,11 @@
error = sysctl_wire_old_buffer(req, 0);
if (error)
return (error);
+ sx_slock(&proctree_lock);
error = pget((pid_t)name[0], PGET_CANSEE, &p);
if (error == 0)
error = sysctl_out_proc(p, req, flags);
+ sx_sunlock(&proctree_lock);
return (error);
}
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -333,7 +333,7 @@
error = 0;
pgrp = NULL;
- newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
+ newpgrp = uma_zalloc(pgrp_zone, M_WAITOK);
newsess = malloc(sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
sx_xlock(&proctree_lock);
@@ -351,10 +351,8 @@
sx_xunlock(&proctree_lock);
- if (newpgrp != NULL)
- free(newpgrp, M_PGRP);
- if (newsess != NULL)
- free(newsess, M_SESSION);
+ uma_zfree(pgrp_zone, newpgrp);
+ free(newsess, M_SESSION);
return (error);
}
@@ -393,7 +391,7 @@
error = 0;
- newpgrp = malloc(sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
+ newpgrp = uma_zalloc(pgrp_zone, M_WAITOK);
sx_xlock(&proctree_lock);
if (uap->pid != 0 && uap->pid != curp->p_pid) {
@@ -456,8 +454,7 @@
sx_xunlock(&proctree_lock);
KASSERT((error == 0) || (newpgrp != NULL),
("setpgid failed and newpgrp is NULL"));
- if (newpgrp != NULL)
- free(newpgrp, M_PGRP);
+ uma_zfree(pgrp_zone, newpgrp);
return (error);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2227,9 +2227,9 @@
* is default; don't stop the process below if sleeping,
* and don't clear any pending SIGCONT.
*/
- if ((prop & SIGPROP_TTYSTOP) &&
- (p->p_pgrp->pg_jobc == 0) &&
- (action == SIG_DFL)) {
+ if ((prop & SIGPROP_TTYSTOP) != 0 &&
+ (p->p_pgrp->pg_flags & PGRP_ORPHANED) != 0 &&
+ action == SIG_DFL) {
if (ksi && (ksi->ksi_flags & KSI_INS))
ksiginfo_tryfree(ksi);
return (ret);
@@ -2984,17 +2984,20 @@
* should ignore tty stops.
*/
if (prop & SIGPROP_STOP) {
- if (p->p_flag &
- (P_TRACED | P_WEXIT | P_SINGLE_EXIT) ||
- (p->p_pgrp->pg_jobc == 0 &&
- prop & SIGPROP_TTYSTOP))
+ mtx_unlock(&ps->ps_mtx);
+ if ((p->p_flag & (P_TRACED | P_WEXIT |
+ P_SINGLE_EXIT)) != 0 || ((p->p_pgrp->
+ pg_flags & PGRP_ORPHANED) != 0 &&
+ (prop & SIGPROP_TTYSTOP) != 0)) {
+ mtx_lock(&ps->ps_mtx);
break; /* == ignore */
+ }
if (TD_SBDRY_INTR(td)) {
KASSERT((td->td_flags & TDF_SBDRY) != 0,
("lost TDF_SBDRY"));
+ mtx_lock(&ps->ps_mtx);
return (-1);
}
- mtx_unlock(&ps->ps_mtx);
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
&p->p_mtx.lock_object, "Catching SIGSTOP");
sigqueue_delete(&td->td_sigqueue, sig);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -423,7 +423,7 @@
int
tty_wait_background(struct tty *tp, struct thread *td, int sig)
{
- struct proc *p = td->td_proc;
+ struct proc *p;
struct pgrp *pg;
ksiginfo_t ksi;
int error;
@@ -431,8 +431,22 @@
MPASS(sig == SIGTTIN || sig == SIGTTOU);
tty_assert_locked(tp);
+ p = td->td_proc;
for (;;) {
+ pg = p->p_pgrp;
+ PGRP_LOCK(pg);
PROC_LOCK(p);
+
+ /*
+ * pg may no longer be our process group.
+ * Re-check after locking.
+ */
+ if (p->p_pgrp != pg) {
+ PROC_UNLOCK(p);
+ PGRP_UNLOCK(pg);
+ continue;
+ }
+
/*
* The process should only sleep, when:
* - This terminal is the controlling terminal
@@ -445,6 +459,7 @@
if (!tty_is_ctty(tp, p) || p->p_pgrp == tp->t_pgrp) {
/* Allow the action to happen. */
PROC_UNLOCK(p);
+ PGRP_UNLOCK(pg);
return (0);
}
@@ -452,13 +467,15 @@
SIGISMEMBER(td->td_sigmask, sig)) {
/* Only allow them in write()/ioctl(). */
PROC_UNLOCK(p);
+ PGRP_UNLOCK(pg);
return (sig == SIGTTOU ? 0 : EIO);
}
- pg = p->p_pgrp;
- if (p->p_flag & P_PPWAIT || pg->pg_jobc == 0) {
+ if ((p->p_flag & P_PPWAIT) != 0 ||
+ (pg->pg_flags & PGRP_ORPHANED) != 0) {
/* Don't allow the action to happen. */
PROC_UNLOCK(p);
+ PGRP_UNLOCK(pg);
return (EIO);
}
PROC_UNLOCK(p);
@@ -473,20 +490,7 @@
ksi.ksi_signo = sig;
sig = 0;
}
- PGRP_LOCK(pg);
-
- /*
- * pg may no longer be our process group.
- * Re-check after locking process group.
- */
- PROC_LOCK(p);
- if (p->p_pgrp != pg) {
- PROC_UNLOCK(p);
- PGRP_UNLOCK(pg);
- continue;
- }
- PROC_UNLOCK(p);
pgsignal(pg, ksi.ksi_signo, 1, &ksi);
PGRP_UNLOCK(pg);
@@ -2392,9 +2396,8 @@
_db_show_hooks("\t", tp->t_hook);
/* Process info. */
- db_printf("\tpgrp: %p gid %d jobc %d\n", tp->t_pgrp,
- tp->t_pgrp ? tp->t_pgrp->pg_id : 0,
- tp->t_pgrp ? tp->t_pgrp->pg_jobc : 0);
+ db_printf("\tpgrp: %p gid %d\n", tp->t_pgrp,
+ tp->t_pgrp ? tp->t_pgrp->pg_id : 0);
db_printf("\tsession: %p", tp->t_session);
if (tp->t_session != NULL)
db_printf(" count %u leader %p tty %p sid %d login %s",
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -111,10 +111,12 @@
struct session *pg_session; /* (c) Pointer to session. */
struct sigiolst pg_sigiolst; /* (m) List of sigio sources. */
pid_t pg_id; /* (c) Process group id. */
- int pg_jobc; /* (m) Job control process count. */
struct mtx pg_mtx; /* Mutex to protect members */
+ int pg_flags; /* (m) PGRP_ flags */
};
+#define PGRP_ORPHANED 0x00000001 /* Group is orphaned */
+
/*
* pargs, used to hold a copy of the command line, if it had a sane length.
*/
@@ -864,7 +866,6 @@
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_PARGS);
-MALLOC_DECLARE(M_PGRP);
MALLOC_DECLARE(M_SESSION);
MALLOC_DECLARE(M_SUBPROC);
#endif
@@ -1022,6 +1023,7 @@
extern struct proc *initproc, *pageproc; /* Process slots for init, pager. */
extern struct uma_zone *proc_zone;
+extern struct uma_zone *pgrp_zone;
struct proc *pfind(pid_t); /* Find process by id. */
struct proc *pfind_any(pid_t); /* Find (zombie) process by id. */

File Metadata

Mime Type
text/plain
Expires
Mon, May 11, 10:20 PM (57 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28688004
Default Alt Text
D27871.1778538006.diff (20 KB)

Event Timeline