From b66121cd0da62fdcf4b6d4c95d15244be945ec43 Mon Sep 17 00:00:00 2001 From: marcel Date: Sun, 28 Dec 2014 19:03:29 +0000 Subject: [PATCH] MFC r272789: Fix draining in ttydev_leave(). git-svn-id: svn://svn.freebsd.org/base/stable/10@276339 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/kern/tty.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index c244ff60e..44fc9244d 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) { -- 2.45.0