diff options
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 46 |
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 2eefaa6e3e3a..aa48367a0c79 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -390,10 +390,10 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver); * Locking: ctrl_lock */ -int tty_check_change(struct tty_struct *tty) +int __tty_check_change(struct tty_struct *tty, int sig) { unsigned long flags; - struct pid *pgrp; + struct pid *pgrp, *tty_pgrp; int ret = 0; if (current->signal->tty != tty) @@ -403,33 +403,35 @@ int tty_check_change(struct tty_struct *tty) pgrp = task_pgrp(current); spin_lock_irqsave(&tty->ctrl_lock, flags); - - if (!tty->pgrp) { - printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); - goto out_unlock; - } - if (pgrp == tty->pgrp) - goto out_unlock; + tty_pgrp = tty->pgrp; spin_unlock_irqrestore(&tty->ctrl_lock, flags); - if (is_ignored(SIGTTOU)) - goto out_rcuunlock; - if (is_current_pgrp_orphaned()) { - ret = -EIO; - goto out_rcuunlock; + if (tty_pgrp && pgrp != tty->pgrp) { + if (is_ignored(sig)) { + if (sig == SIGTTIN) + ret = -EIO; + } else if (is_current_pgrp_orphaned()) + ret = -EIO; + else { + kill_pgrp(pgrp, sig, 1); + set_thread_flag(TIF_SIGPENDING); + ret = -ERESTARTSYS; + } } - kill_pgrp(pgrp, SIGTTOU, 1); - rcu_read_unlock(); - set_thread_flag(TIF_SIGPENDING); - ret = -ERESTARTSYS; - return ret; -out_unlock: - spin_unlock_irqrestore(&tty->ctrl_lock, flags); -out_rcuunlock: rcu_read_unlock(); + + if (!tty_pgrp) { + pr_warn("%s: tty_check_change: sig=%d, tty->pgrp == NULL!\n", + tty_name(tty), sig); + } + return ret; } +int tty_check_change(struct tty_struct *tty) +{ + return __tty_check_change(tty, SIGTTOU); +} EXPORT_SYMBOL(tty_check_change); static ssize_t hung_up_tty_read(struct file *file, char __user *buf, |