aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2020-12-31 13:45:06 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-01-10 02:41:20 +0000
commita008bdeda3b8278fe600cf83ecf44acd1ccb30b6 (patch)
treec1d6b034d6e17f273fee71ea54326521feee873f
parentef739c7373d8b3833979ad471b31cb9e215411fd (diff)
downloadsrc-a008bdeda3b8278fe600cf83ecf44acd1ccb30b6.tar.gz
src-a008bdeda3b8278fe600cf83ecf44acd1ccb30b6.zip
tty_wait_background: improve locking.
Increase the scope of the process group lock ownership. This ensures that we are consistent in returning EIO for tty write from an orphan and delivery of TTYOUT signals. Reviewed by: jilles Tested by: pho MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D27871
-rw-r--r--sys/kern/tty.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index af4aebd18979..1f86507a6025 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -423,7 +423,7 @@ tty_is_ctty(struct tty *tp, struct proc *p)
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 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
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 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
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,14 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
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) != 0 || pg->pg_jobc == 0) {
/* Don't allow the action to happen. */
PROC_UNLOCK(p);
+ PGRP_UNLOCK(pg);
return (EIO);
}
PROC_UNLOCK(p);
@@ -473,20 +489,7 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
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);