svn commit: r242892 - in stable/9/sys: kern sys
Ed Schouten
ed at FreeBSD.org
Sun Nov 11 12:12:44 UTC 2012
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);
More information about the svn-src-stable-9
mailing list