From ae88b227912c0ec48a0dde46fe47f423ca864059 Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 25 Oct 2012 09:05:21 +0000 Subject: [PATCH] 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 MFC after: 2 weeks --- sys/kern/tty.c | 9 +-------- sys/kern/tty_ttydisc.c | 16 ++++++++++++++++ sys/sys/tty.h | 1 + 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/sys/kern/tty.c b/sys/kern/tty.c index e9c0fb6fe554..4da8d384a8e4 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -361,7 +361,7 @@ tty_is_ctty(struct tty *tp, struct proc *p) 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 *uio, int ioflag) 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); diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c index 52a5df2e580d..63b144ac79d2 100644 --- a/sys/kern/tty_ttydisc.c +++ b/sys/kern/tty_ttydisc.c @@ -126,6 +126,10 @@ ttydisc_read_canonical(struct tty *tp, struct uio *uio, int ioflag) 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 @@ -192,6 +196,10 @@ ttydisc_read_raw_no_timer(struct tty *tp, struct uio *uio, int ioflag) */ 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) @@ -229,6 +237,10 @@ ttydisc_read_raw_read_timer(struct tty *tp, struct uio *uio, int ioflag, 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) @@ -278,6 +290,10 @@ ttydisc_read_raw_interbyte_timer(struct tty *tp, struct uio *uio, int ioflag) */ 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) diff --git a/sys/sys/tty.h b/sys/sys/tty.h index 42f264b9545d..96b88212bde9 100644 --- a/sys/sys/tty.h +++ b/sys/sys/tty.h @@ -180,6 +180,7 @@ void tty_signal_sessleader(struct tty *tp, int signal); 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);