Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145812006
D27871.1778538006.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D27871.1778538006.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D27871: Rework jobc handling.
Attached
Detach File
Event Timeline
Log In to Comment