summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2020-05-08 07:31:47 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2020-05-08 07:31:47 +0000
commitb6734bf8f2673f2586822c2d999306b09f29c2d6 (patch)
tree3be4e0f1abf08ea612e7afdf308e06e4f1d0fa1e /sys
parentf3087c83d72544f09ca149160d476baacec50258 (diff)
Do not wait indefinitely for flushing when closing a tty.
This prevent exiting processes from hanging when a slave pseudo terminal is close(2)d before its master. From NetBSD via anton@. Reported-by: syzbot+2ed25b5c40d11e4c3beb@syzkaller.appspotmail.com ok anton@, kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/tty.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 431b22653de..e9f98f87e01 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.154 2020/04/07 13:27:51 visa Exp $ */
+/* $OpenBSD: tty.c,v 1.155 2020/05/08 07:31:46 mpi Exp $ */
/* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */
/*-
@@ -80,6 +80,8 @@ void filt_ttyrdetach(struct knote *kn);
int filt_ttywrite(struct knote *kn, long hint);
void filt_ttywdetach(struct knote *kn);
void ttystats_init(struct itty **, size_t *);
+int ttywait_nsec(struct tty *, uint64_t);
+int ttysleep_nsec(struct tty *, void *, int, char *, uint64_t);
/* Symbolic sleep message strings. */
char ttclos[] = "ttycls";
@@ -1202,10 +1204,10 @@ ttnread(struct tty *tp)
}
/*
- * Wait for output to drain.
+ * Wait for output to drain, or if this times out, flush it.
*/
int
-ttywait(struct tty *tp)
+ttywait_nsec(struct tty *tp, uint64_t nsecs)
{
int error, s;
@@ -1219,7 +1221,10 @@ ttywait(struct tty *tp)
(ISSET(tp->t_state, TS_CARR_ON) || ISSET(tp->t_cflag, CLOCAL))
&& tp->t_oproc) {
SET(tp->t_state, TS_ASLEEP);
- error = ttysleep(tp, &tp->t_outq, TTOPRI | PCATCH, ttyout);
+ error = ttysleep_nsec(tp, &tp->t_outq, TTOPRI | PCATCH,
+ ttyout, nsecs);
+ if (error == EWOULDBLOCK)
+ ttyflush(tp, FWRITE);
if (error)
break;
} else
@@ -1229,6 +1234,12 @@ ttywait(struct tty *tp)
return (error);
}
+int
+ttywait(struct tty *tp)
+{
+ return (ttywait_nsec(tp, INFSLP));
+}
+
/*
* Flush if successfully wait.
*/
@@ -1237,7 +1248,8 @@ ttywflush(struct tty *tp)
{
int error;
- if ((error = ttywait(tp)) == 0)
+ error = ttywait_nsec(tp, SEC_TO_NSEC(5));
+ if (error == 0 || error == EWOULDBLOCK)
ttyflush(tp, FREAD);
return (error);
}
@@ -2281,11 +2293,17 @@ tputchar(int c, struct tty *tp)
int
ttysleep(struct tty *tp, void *chan, int pri, char *wmesg)
{
+ return (ttysleep_nsec(tp, chan, pri, wmesg, INFSLP));
+}
+
+int
+ttysleep_nsec(struct tty *tp, void *chan, int pri, char *wmesg, uint64_t nsecs)
+{
int error;
short gen;
gen = tp->t_gen;
- if ((error = tsleep_nsec(chan, pri, wmesg, INFSLP)) != 0)
+ if ((error = tsleep_nsec(chan, pri, wmesg, nsecs)) != 0)
return (error);
return (tp->t_gen == gen ? 0 : ERESTART);
}