Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 11 Nov 2012 12:12:44 +0000 (UTC)
From:      Ed Schouten <ed@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r242892 - in stable/9/sys: kern sys
Message-ID:  <201211111212.qABCCiHA081554@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ed
Date: Sun Nov 11 12:12:44 2012
New Revision: 242892
URL: http://svnweb.freebsd.org/changeset/base/242892

Log:
  MFC r241161:
  
    Fix faulty error code handling in read(2) on TTYs.
  
    When performing a non-blocking read(2), on a TTY while no data is
    available, we should return EAGAIN. But if there's a modem disconnect,
    we should return 0. Right now we only return 0 when doing a blocking
    read, which is wrong.
  
  MFC r242078:
  
    Correct SIGTTIN handling.
  
    In the old TTY layer, SIGTTIN was correctly handled like this:
  
          while (data should be read) {
                  send SIGTTIN if not foreground process group
                  read data
          }
  
    In the new TTY layer, however, this behaviour was changed, based on a
    false interpretation of the standard:
  
          send SIGTTIN if not foreground process group
          while (data should be read) {
                  read data
          }
  
    Correct this by pushing tty_wait_background() into the ttydisc_read_*()
    functions.
  
    Reported by:  koitsu
    PR:           kern/173010

Modified:
  stable/9/sys/kern/tty.c
  stable/9/sys/kern/tty_ttydisc.c
  stable/9/sys/sys/tty.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/kern/tty.c
==============================================================================
--- stable/9/sys/kern/tty.c	Sun Nov 11 12:06:12 2012	(r242891)
+++ stable/9/sys/kern/tty.c	Sun Nov 11 12:12:44 2012	(r242892)
@@ -361,7 +361,7 @@ tty_is_ctty(struct tty *tp, struct proc 
 	return (p->p_session == tp->t_session && p->p_flag & P_CONTROLT);
 }
 
-static int
+int
 tty_wait_background(struct tty *tp, struct thread *td, int sig)
 {
 	struct proc *p = td->td_proc;
@@ -433,13 +433,6 @@ ttydev_read(struct cdev *dev, struct uio
 	error = ttydev_enter(tp);
 	if (error)
 		goto done;
-
-	error = tty_wait_background(tp, curthread, SIGTTIN);
-	if (error) {
-		tty_unlock(tp);
-		goto done;
-	}
-
 	error = ttydisc_read(tp, uio, ioflag);
 	tty_unlock(tp);
 

Modified: stable/9/sys/kern/tty_ttydisc.c
==============================================================================
--- stable/9/sys/kern/tty_ttydisc.c	Sun Nov 11 12:06:12 2012	(r242891)
+++ stable/9/sys/kern/tty_ttydisc.c	Sun Nov 11 12:12:44 2012	(r242892)
@@ -126,6 +126,10 @@ ttydisc_read_canonical(struct tty *tp, s
 	breakc[n] = '\0';
 
 	do {
+		error = tty_wait_background(tp, curthread, SIGTTIN);
+		if (error)
+			return (error);
+
 		/*
 		 * Quite a tricky case: unlike the old TTY
 		 * implementation, this implementation copies data back
@@ -149,10 +153,10 @@ ttydisc_read_canonical(struct tty *tp, s
 
 		/* No more data. */
 		if (clen == 0) {
-			if (ioflag & IO_NDELAY)
-				return (EWOULDBLOCK);
-			else if (tp->t_flags & TF_ZOMBIE)
+			if (tp->t_flags & TF_ZOMBIE)
 				return (0);
+			else if (ioflag & IO_NDELAY)
+				return (EWOULDBLOCK);
 
 			error = tty_wait(tp, &tp->t_inwait);
 			if (error)
@@ -192,6 +196,10 @@ ttydisc_read_raw_no_timer(struct tty *tp
 	 */
 
 	for (;;) {
+		error = tty_wait_background(tp, curthread, SIGTTIN);
+		if (error)
+			return (error);
+
 		error = ttyinq_read_uio(&tp->t_inq, tp, uio,
 		    uio->uio_resid, 0);
 		if (error)
@@ -200,10 +208,10 @@ ttydisc_read_raw_no_timer(struct tty *tp
 			return (0);
 
 		/* We have to wait for more. */
-		if (ioflag & IO_NDELAY)
-			return (EWOULDBLOCK);
-		else if (tp->t_flags & TF_ZOMBIE)
+		if (tp->t_flags & TF_ZOMBIE)
 			return (0);
+		else if (ioflag & IO_NDELAY)
+			return (EWOULDBLOCK);
 
 		error = tty_wait(tp, &tp->t_inwait);
 		if (error)
@@ -229,6 +237,10 @@ ttydisc_read_raw_read_timer(struct tty *
 	timevaladd(&end, &now);
 
 	for (;;) {
+		error = tty_wait_background(tp, curthread, SIGTTIN);
+		if (error)
+			return (error);
+
 		error = ttyinq_read_uio(&tp->t_inq, tp, uio,
 		    uio->uio_resid, 0);
 		if (error)
@@ -248,10 +260,10 @@ ttydisc_read_raw_read_timer(struct tty *
 		 * We have to wait for more. If the timer expires, we
 		 * should return a 0-byte read.
 		 */
-		if (ioflag & IO_NDELAY)
-			return (EWOULDBLOCK);
-		else if (tp->t_flags & TF_ZOMBIE)
+		if (tp->t_flags & TF_ZOMBIE)
 			return (0);
+		else if (ioflag & IO_NDELAY)
+			return (EWOULDBLOCK);
 
 		error = tty_timedwait(tp, &tp->t_inwait, hz);
 		if (error)
@@ -278,6 +290,10 @@ ttydisc_read_raw_interbyte_timer(struct 
 	 */
 
 	for (;;) {
+		error = tty_wait_background(tp, curthread, SIGTTIN);
+		if (error)
+			return (error);
+
 		error = ttyinq_read_uio(&tp->t_inq, tp, uio,
 		    uio->uio_resid, 0);
 		if (error)
@@ -293,10 +309,10 @@ ttydisc_read_raw_interbyte_timer(struct 
 			break;
 
 		/* We have to wait for more. */
-		if (ioflag & IO_NDELAY)
-			return (EWOULDBLOCK);
-		else if (tp->t_flags & TF_ZOMBIE)
+		if (tp->t_flags & TF_ZOMBIE)
 			return (0);
+		else if (ioflag & IO_NDELAY)
+			return (EWOULDBLOCK);
 
 		error = tty_wait(tp, &tp->t_inwait);
 		if (error)

Modified: stable/9/sys/sys/tty.h
==============================================================================
--- stable/9/sys/sys/tty.h	Sun Nov 11 12:06:12 2012	(r242891)
+++ stable/9/sys/sys/tty.h	Sun Nov 11 12:12:44 2012	(r242892)
@@ -180,6 +180,7 @@ void	tty_signal_sessleader(struct tty *t
 void	tty_signal_pgrp(struct tty *tp, int signal);
 /* Waking up readers/writers. */
 int	tty_wait(struct tty *tp, struct cv *cv);
+int	tty_wait_background(struct tty *tp, struct thread *td, int sig);
 int	tty_timedwait(struct tty *tp, struct cv *cv, int timo);
 void	tty_wakeup(struct tty *tp, int flags);
 



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