Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 28 Dec 2014 19:03:30 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r276339 - stable/10/sys/kern
Message-ID:  <201412281903.sBSJ3UJK018665@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Sun Dec 28 19:03:29 2014
New Revision: 276339
URL: https://svnweb.freebsd.org/changeset/base/276339

Log:
  MFC r272789:
  Fix draining in ttydev_leave().

Modified:
  stable/10/sys/kern/tty.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/kern/tty.c
==============================================================================
--- stable/10/sys/kern/tty.c	Sun Dec 28 18:53:16 2014	(r276338)
+++ stable/10/sys/kern/tty.c	Sun Dec 28 19:03:29 2014	(r276339)
@@ -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
 
 		/* 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
 	}
 	case TIOCDRAIN:
 		/* Drain TTY output. */
-		return tty_drain(tp);
+		return tty_drain(tp, 0);
 	case TIOCCONS:
 		/* Set terminal as console TTY. */
 		if (*(int *)data) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201412281903.sBSJ3UJK018665>