|
@@ -559,6 +559,9 @@ void __tty_hangup(struct tty_struct *tty)
|
|
|
|
|
|
tty_lock();
|
|
|
|
|
|
+ /* some functions below drop BTM, so we need this bit */
|
|
|
+ set_bit(TTY_HUPPING, &tty->flags);
|
|
|
+
|
|
|
/* inuse_filps is protected by the single tty lock,
|
|
|
this really needs to change if we want to flush the
|
|
|
workqueue with the lock held */
|
|
@@ -578,6 +581,10 @@ void __tty_hangup(struct tty_struct *tty)
|
|
|
}
|
|
|
spin_unlock(&tty_files_lock);
|
|
|
|
|
|
+ /*
|
|
|
+ * it drops BTM and thus races with reopen
|
|
|
+ * we protect the race by TTY_HUPPING
|
|
|
+ */
|
|
|
tty_ldisc_hangup(tty);
|
|
|
|
|
|
read_lock(&tasklist_lock);
|
|
@@ -615,7 +622,6 @@ void __tty_hangup(struct tty_struct *tty)
|
|
|
tty->session = NULL;
|
|
|
tty->pgrp = NULL;
|
|
|
tty->ctrl_status = 0;
|
|
|
- set_bit(TTY_HUPPED, &tty->flags);
|
|
|
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
|
|
|
|
|
|
/* Account for the p->signal references we killed */
|
|
@@ -641,6 +647,7 @@ void __tty_hangup(struct tty_struct *tty)
|
|
|
* can't yet guarantee all that.
|
|
|
*/
|
|
|
set_bit(TTY_HUPPED, &tty->flags);
|
|
|
+ clear_bit(TTY_HUPPING, &tty->flags);
|
|
|
tty_ldisc_enable(tty);
|
|
|
|
|
|
tty_unlock();
|
|
@@ -1311,6 +1318,7 @@ static int tty_reopen(struct tty_struct *tty)
|
|
|
struct tty_driver *driver = tty->driver;
|
|
|
|
|
|
if (test_bit(TTY_CLOSING, &tty->flags) ||
|
|
|
+ test_bit(TTY_HUPPING, &tty->flags) ||
|
|
|
test_bit(TTY_LDISC_CHANGING, &tty->flags))
|
|
|
return -EIO;
|
|
|
|