summaryrefslogtreecommitdiff
path: root/drivers/tty/vt/selection.c
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2016-01-10 22:41:01 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-01-27 15:01:44 -0800
commite55afd11a48354c810caf6b6ad4c103016a88230 (patch)
treeeb073c28c1e21785fcbe92740ce1290da7fcb85c /drivers/tty/vt/selection.c
parent5b6e6832f41c9422753804671ee06af37ac8caf6 (diff)
tty: Prepare for destroying line discipline on hangup
tty file_operations (read/write/ioctl) wait for the ldisc reference indefinitely (until ldisc lifetime events, such as hangup or TIOCSETD, finish). Since hangup now destroys the ldisc and does not instance another copy, file_operations must now be prepared to receive a NULL ldisc reference from tty_ldisc_ref_wait(): CPU 0 CPU 1 ----- ----- (*f_op->read)() => tty_read() __tty_hangup() ... f_op = &hung_up_tty_fops; ... tty_ldisc_hangup() tty_ldisc_lock() tty_ldisc_kill() tty->ldisc = NULL tty_ldisc_unlock() ld = tty_ldisc_ref_wait() /* ld == NULL */ Instead, the action taken now is to return the same value as if the tty had been hungup a moment earlier: CPU 0 CPU 1 ----- ----- __tty_hangup() ... f_op = &hung_up_tty_fops; (*f_op->read)() => hung_up_tty_read() return 0; ... tty_ldisc_hangup() tty_ldisc_lock() tty_ldisc_kill() tty->ldisc = NULL tty_ldisc_unlock() Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/vt/selection.c')
-rw-r--r--drivers/tty/vt/selection.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 381a2b13682c..4dd9dd2270a0 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -347,6 +347,8 @@ int paste_selection(struct tty_struct *tty)
console_unlock();
ld = tty_ldisc_ref_wait(tty);
+ if (!ld)
+ return -EIO; /* ldisc was hung up */
tty_buffer_lock_exclusive(&vc->port);
add_wait_queue(&vc->paste_wait, &wait);