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) {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to