mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-03-29 10:24:08 +00:00
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: Alan Cox <alan@linux.intel.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
1bb954153a
commit
52bce7f8d4
2 changed files with 22 additions and 27 deletions
|
@ -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)) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
timeout = schedule_timeout(timeout);
|
|
||||||
|
|
||||||
down_read(&tty->termios_rwsem);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
down_read(&tty->termios_rwsem);
|
||||||
|
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)
|
||||||
/* 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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue