mirror of
https://github.com/torvalds/linux.git
synced 2026-06-09 07:03:37 +02:00
TTY: ldisc, wait for ldisc infinitely in hangup
commit0c73c08ec7upstream. For /dev/console case, we do not kill all ldisc users. It's due to redirected_tty_write test in __tty_hangup. In that case there still might be a process waiting e.g. in n_tty_read for input. We wait for such processes to disappear. The problem is that we use a timeout. After this timeout, we continue closing the ldisc and start freeing tty resources. It obviously leads to crashes when the other process is woken. So to fix this, we wait infinitely before reiniting the ldisc. (The tiocsetd remains untouched -- times out after 5s.) This is nicely reproducible with this run from shell: exec 0<>/dev/console 1<>/dev/console 2<>/dev/console and stopping a getty like: systemctl stop serial-getty@ttyS0.service The crash proper may be produced only under load or with constified timing the same as for92f6fa09b. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Cc: Dave Young <hidave.darkstar@gmail.com> Cc: Dave Jones <davej@redhat.com> Cc: Ben Hutchings <ben@decadent.org.uk> Cc: Dmitriy Matrosov <sgf.dma@gmail.com> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
57ee681901
commit
ecaaa92488
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/nsproxy.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
/*
|
||||
* This guards the refcounted line discipline lists. The lock
|
||||
|
|
@ -838,7 +839,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
|||
tty_unlock();
|
||||
cancel_work_sync(&tty->buf.work);
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
|
||||
retry:
|
||||
tty_lock();
|
||||
mutex_lock(&tty->ldisc_mutex);
|
||||
|
||||
|
|
@ -847,7 +848,21 @@ void tty_ldisc_hangup(struct tty_struct *tty)
|
|||
it means auditing a lot of other paths so this is
|
||||
a FIXME */
|
||||
if (tty->ldisc) { /* Not yet closed */
|
||||
WARN_ON_ONCE(tty_ldisc_wait_idle(tty, 5 * HZ));
|
||||
if (atomic_read(&tty->ldisc->users) != 1) {
|
||||
char cur_n[TASK_COMM_LEN], tty_n[64];
|
||||
long timeout = 3 * HZ;
|
||||
tty_unlock();
|
||||
|
||||
while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
|
||||
timeout = MAX_SCHEDULE_TIMEOUT;
|
||||
printk_ratelimited(KERN_WARNING
|
||||
"%s: waiting (%s) for %s took too long, but we keep waiting...\n",
|
||||
__func__, get_task_comm(cur_n, current),
|
||||
tty_name(tty, tty_n));
|
||||
}
|
||||
mutex_unlock(&tty->ldisc_mutex);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
if (reset == 0) {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user