Commit 52bce7f8 authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

pty, n_tty: Simplify input processing on final close

When releasing one end of a pty pair, that end may just have written
to the other, which the input processing worker, flush_to_ldisc(), is
still working on but has not completed the copy to the other end's
read buffer. So input may not appear to be available to a waiting
reader but yet TTY_OTHER_CLOSED is now observed. The n_tty line
discipline has worked around this by waiting for input processing
to complete and then re-checking if input is available before
exiting with -EIO.

Since the tty/ldisc lock reordering, the wait for input processing
to complete can now occur during final close before setting
TTY_OTHER_CLOSED. In this way, a waiting reader is guaranteed to
see input available (if any) before observing TTY_OTHER_CLOSED.
Reviewed-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1bb95415
...@@ -2197,34 +2197,28 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, ...@@ -2197,34 +2197,28 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
if (!input_available_p(tty, 0)) { if (!input_available_p(tty, 0)) {
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
up_read(&tty->termios_rwsem); retval = -EIO;
tty_flush_to_ldisc(tty); break;
down_read(&tty->termios_rwsem); }
if (!input_available_p(tty, 0)) { if (tty_hung_up_p(file))
retval = -EIO; break;
break; if (!timeout)
} break;
} else { if (file->f_flags & O_NONBLOCK) {
if (tty_hung_up_p(file)) retval = -EAGAIN;
break; break;
if (!timeout) }
break; if (signal_pending(current)) {
if (file->f_flags & O_NONBLOCK) { retval = -ERESTARTSYS;
retval = -EAGAIN; break;
break; }
} n_tty_set_room(tty);
if (signal_pending(current)) { up_read(&tty->termios_rwsem);
retval = -ERESTARTSYS;
break;
}
n_tty_set_room(tty);
up_read(&tty->termios_rwsem);
timeout = schedule_timeout(timeout); timeout = schedule_timeout(timeout);
down_read(&tty->termios_rwsem); down_read(&tty->termios_rwsem);
continue; continue;
}
} }
__set_current_state(TASK_RUNNING); __set_current_state(TASK_RUNNING);
......
...@@ -53,6 +53,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) ...@@ -53,6 +53,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
/* Review - krefs on tty_link ?? */ /* Review - krefs on tty_link ?? */
if (!tty->link) if (!tty->link)
return; return;
tty_flush_to_ldisc(tty->link);
set_bit(TTY_OTHER_CLOSED, &tty->link->flags); set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait); wake_up_interruptible(&tty->link->write_wait);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment