summaryrefslogtreecommitdiffstats
path: root/sys/kern/tty.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2014-12-28 19:03:29 +0000
committermarcel <marcel@FreeBSD.org>2014-12-28 19:03:29 +0000
commit585f5c8ddaef5e9b9ba675ab11a5e8481aa0c425 (patch)
tree2a174ec9a50c7b00ecec743314d68e153296f39d /sys/kern/tty.c
parent5fceeec31e9289a8ab54c552977aef692689a17c (diff)
downloadFreeBSD-src-585f5c8ddaef5e9b9ba675ab11a5e8481aa0c425.zip
FreeBSD-src-585f5c8ddaef5e9b9ba675ab11a5e8481aa0c425.tar.gz
MFC r272789:
Fix draining in ttydev_leave().
Diffstat (limited to 'sys/kern/tty.c')
-rw-r--r--sys/kern/tty.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index c244ff6..44fc924 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -123,9 +123,10 @@ tty_watermarks(struct tty *tp)
}
static int
-tty_drain(struct tty *tp)
+tty_drain(struct tty *tp, int leaving)
{
- int error;
+ size_t bytesused;
+ int error, revokecnt;
if (ttyhook_hashook(tp, getc_inject))
/* buffer is inaccessible */
@@ -134,11 +135,27 @@ tty_drain(struct tty *tp)
while (ttyoutq_bytesused(&tp->t_outq) > 0) {
ttydevsw_outwakeup(tp);
/* Could be handled synchronously. */
- if (ttyoutq_bytesused(&tp->t_outq) == 0)
+ bytesused = ttyoutq_bytesused(&tp->t_outq);
+ if (bytesused == 0)
return (0);
/* Wait for data to be drained. */
- error = tty_wait(tp, &tp->t_outwait);
+ if (leaving) {
+ revokecnt = tp->t_revokecnt;
+ error = tty_timedwait(tp, &tp->t_outwait, hz);
+ switch (error) {
+ case ERESTART:
+ if (revokecnt != tp->t_revokecnt)
+ error = 0;
+ break;
+ case EWOULDBLOCK:
+ if (ttyoutq_bytesused(&tp->t_outq) < bytesused)
+ error = 0;
+ break;
+ }
+ } else
+ error = tty_wait(tp, &tp->t_outwait);
+
if (error)
return (error);
}
@@ -191,10 +208,8 @@ ttydev_leave(struct tty *tp)
/* Drain any output. */
MPASS((tp->t_flags & TF_STOPPED) == 0);
- if (!tty_gone(tp)) {
- while (tty_drain(tp) == ERESTART)
- ;
- }
+ if (!tty_gone(tp))
+ tty_drain(tp, 1);
ttydisc_close(tp);
@@ -1549,7 +1564,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
/* Set terminal flags through tcsetattr(). */
if (cmd == TIOCSETAW || cmd == TIOCSETAF) {
- error = tty_drain(tp);
+ error = tty_drain(tp, 0);
if (error)
return (error);
if (cmd == TIOCSETAF)
@@ -1728,7 +1743,7 @@ tty_generic_ioctl(struct tty *tp, u_long cmd, void *data, int fflag,
}
case TIOCDRAIN:
/* Drain TTY output. */
- return tty_drain(tp);
+ return tty_drain(tp, 0);
case TIOCCONS:
/* Set terminal as console TTY. */
if (*(int *)data) {
OpenPOWER on IntegriCloud