diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2016-01-09 21:13:45 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-02-17 12:31:02 -0800 |
commit | b4312250147d42dceed6c8d44aa02cb29539db19 (patch) | |
tree | 1f7fd5ec892b3ed87288565bb07ca893d9efbeb9 /drivers | |
parent | c35f1234931e2cae81726440ad4df8ef1f313219 (diff) | |
download | lwn-b4312250147d42dceed6c8d44aa02cb29539db19.tar.gz lwn-b4312250147d42dceed6c8d44aa02cb29539db19.zip |
tty: Retry failed reopen if tty teardown in-progress
commit 7f22f6c935cda600660e623a411fe380015d28d9 upstream.
A small window exists where a tty reopen will observe the tty
just prior to imminent teardown (tty->count == 0); in this case, open()
returns EIO to userspace.
Instead, retry the open after checking for signals and yielding;
this interruptible retry loop allows teardown to commence and initialize
a new tty on retry. Never retry the BSD master pty reopen; there is no
guarantee the pty pair teardown is imminent since the slave file
descriptors may remain open indefinitely.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/tty/tty_io.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 4d34116842a6..8eda897ec2a0 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1462,13 +1462,13 @@ static int tty_reopen(struct tty_struct *tty) { struct tty_driver *driver = tty->driver; - if (!tty->count) - return -EIO; - if (driver->type == TTY_DRIVER_TYPE_PTY && driver->subtype == PTY_TYPE_MASTER) return -EIO; + if (!tty->count) + return -EAGAIN; + if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN)) return -EBUSY; @@ -2092,7 +2092,11 @@ retry_open: if (IS_ERR(tty)) { retval = PTR_ERR(tty); - goto err_file; + if (retval != -EAGAIN || signal_pending(current)) + goto err_file; + tty_free_file(filp); + schedule(); + goto retry_open; } tty_add_file(tty, filp); |