Skip to content

Commit

Permalink
pty, n_tty: Simplify input processing on final close
Browse files Browse the repository at this point in the history
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: Alan Cox <alan@linux.intel.com>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Peter Hurley authored and Greg Kroah-Hartman committed Nov 6, 2014
1 parent 1bb9541 commit 52bce7f
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 26 deletions.
46 changes: 20 additions & 26 deletions drivers/tty/n_tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -2197,34 +2197,28 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,

if (!input_available_p(tty, 0)) {
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
up_read(&tty->termios_rwsem);
tty_flush_to_ldisc(tty);
down_read(&tty->termios_rwsem);
if (!input_available_p(tty, 0)) {
retval = -EIO;
break;
}
} else {
if (tty_hung_up_p(file))
break;
if (!timeout)
break;
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
n_tty_set_room(tty);
up_read(&tty->termios_rwsem);
retval = -EIO;
break;
}
if (tty_hung_up_p(file))
break;
if (!timeout)
break;
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) {
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);
continue;
}
down_read(&tty->termios_rwsem);
continue;
}
__set_current_state(TASK_RUNNING);

Expand Down
1 change: 1 addition & 0 deletions drivers/tty/pty.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
/* Review - krefs on tty_link ?? */
if (!tty->link)
return;
tty_flush_to_ldisc(tty->link);
set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait);
Expand Down

0 comments on commit 52bce7f

Please sign in to comment.