From 807708844979ba8c6d5717345a8608454992696d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 16 Jul 2009 16:07:03 +0100 Subject: n_tty: Fix echo race If a tty in N_TTY mode with echo enabled manages to get itself into a state where - echo characters are pending - FASYNC is enabled - tty_write_wakeup is called from either - a device write path (pty) - an IRQ (serial) then it either deadlocks or explodes taking a mutex in the IRQ path. On the serial side it is almost impossible to reproduce because you have to go from a full serial port to a near empty one with echo characters pending. The pty case happens to have become possible to trigger using emacs and ptys, the pty changes having created a scenario which shows up this bug. The code path is n_tty:process_echoes() (takes mutex) tty_io:tty_put_char() pty:pty_write (or serial paths) tty_wakeup (from pty_write or serial IRQ) n_tty_write_wakeup() process_echoes() *KABOOM* Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/n_tty.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/char/n_tty.c') diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 94a5d5020ab..ff47907ff1b 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1331,9 +1331,6 @@ handle_newline: static void n_tty_write_wakeup(struct tty_struct *tty) { - /* Write out any echoed characters that are still pending */ - process_echoes(tty); - if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) kill_fasync(&tty->fasync, SIGIO, POLL_OUT); } -- cgit v1.2.3 From e043e42bdb66885b3ac10d27a01ccb9972e2b0a3 Mon Sep 17 00:00:00 2001 From: OGAWA Hirofumi Date: Wed, 29 Jul 2009 12:15:56 -0700 Subject: pty: avoid forcing 'low_latency' tty flag We really don't want to mark the pty as a low-latency device, because as Alan points out, the ->write method can be called from an IRQ (ppp?), and that means we can't use ->low_latency=1 as we take mutexes in the low_latency case. So rather than using low_latency to force the written data to be pushed to the ldisc handling at 'write()' time, just make the reader side (or the poll function) do the flush when it checks whether there is data to be had. This also fixes the problem with lost data in an emacs compile buffer (bugzilla 13815), and we can thus revert the low_latency pty hack (commit 3a54297478e6578f96fd54bf4daa1751130aca86: "pty: quickfix for the pty ENXIO timing problems"). Signed-off-by: OGAWA Hirofumi Tested-by: Aneesh Kumar K.V [ Modified to do the tty_flush_to_ldisc() inside input_available_p() so that it triggers for both read and poll() - Linus] Signed-off-by: Linus Torvalds --- drivers/char/n_tty.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/char/n_tty.c') diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index ff47907ff1b..973be2f4419 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1583,6 +1583,7 @@ static int n_tty_open(struct tty_struct *tty) static inline int input_available_p(struct tty_struct *tty, int amt) { + tty_flush_to_ldisc(tty); if (tty->icanon) { if (tty->canon_data) return 1; -- cgit v1.2.3