diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index adbd9acf817f..ffa31c671a64 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -1755,7 +1755,7 @@ int tty_release(struct inode *inode, struct file *filp) { struct tty_struct *tty = file_tty(filp); struct tty_struct *o_tty; - int pty_master, tty_closing, o_tty_closing, do_sleep; + int pty_master, do_sleep, final; int idx; char buf[64]; @@ -1797,18 +1797,15 @@ int tty_release(struct inode *inode, struct file *filp) * The test for the o_tty closing is necessary, since the master and * slave sides may close in any order. If the slave side closes out * first, its count will be one, since the master side holds an open. - * Thus this test wouldn't be triggered at the time the slave closes, + * Thus this test wouldn't be triggered at the time the slave closed, * so we do it now. */ tty_lock_pair(tty, o_tty); while (1) { - tty_closing = tty->count <= 1; - o_tty_closing = o_tty && - (o_tty->count <= (pty_master ? 1 : 0)); do_sleep = 0; - if (tty_closing) { + if (tty->count <= 1) { if (waitqueue_active(&tty->read_wait)) { wake_up_poll(&tty->read_wait, POLLIN); do_sleep++; @@ -1818,7 +1815,7 @@ int tty_release(struct inode *inode, struct file *filp) do_sleep++; } } - if (o_tty_closing) { + if (pty_master && o_tty->count <= 1) { if (waitqueue_active(&o_tty->read_wait)) { wake_up_poll(&o_tty->read_wait, POLLIN); do_sleep++; @@ -1836,14 +1833,6 @@ int tty_release(struct inode *inode, struct file *filp) schedule(); } - /* - * The closing flags are now consistent with the open counts on - * both sides, and we've completed the last operation that could - * block, so it's safe to proceed with closing. - * - * We must *not* drop the tty_mutex until we ensure that a further - * entry into tty_open can not pick up this tty. - */ if (pty_master) { if (--o_tty->count < 0) { printk(KERN_WARNING "%s: bad pty slave count (%d) for %s\n", @@ -1875,20 +1864,22 @@ int tty_release(struct inode *inode, struct file *filp) * processes that still think tty or o_tty is their controlling * tty. */ - if (tty_closing || o_tty_closing) { + if (!tty->count) { read_lock(&tasklist_lock); session_clear_tty(tty->session); - if (o_tty) + if (pty_master) session_clear_tty(o_tty->session); read_unlock(&tasklist_lock); } + /* check whether both sides are closing ... */ + final = !tty->count && !(pty_master && o_tty->count); + tty_unlock_pair(tty, o_tty); /* At this point, the tty->count == 0 should ensure a dead tty cannot be re-opened by a racing opener */ - /* check whether both sides are closing ... */ - if (!tty_closing || (o_tty && !o_tty_closing)) + if (!final) return 0; #ifdef TTY_DEBUG_HANGUP