From: Benjamin Herrenschmidt ldisc close can race with the flush_to_ldisc workqueue. This patch fixes it by killing the workqueue first. --- 25-akpm/drivers/char/tty_io.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff -puN drivers/char/tty_io.c~fix-race-on-tty-close drivers/char/tty_io.c --- 25/drivers/char/tty_io.c~fix-race-on-tty-close 2004-05-05 22:04:05.108818712 -0700 +++ 25-akpm/drivers/char/tty_io.c 2004-05-05 22:04:05.112818104 -0700 @@ -1267,6 +1267,18 @@ static void release_dev(struct file * fi #endif /* + * Prevent flush_to_ldisc() from rescheduling the work for later. Then + * kill any delayed work. + */ + clear_bit(TTY_DONT_FLIP, &tty->flags); + cancel_delayed_work(&tty->flip.work); + + /* + * Wait for ->hangup_work and ->flip.work handlers to terminate + */ + flush_scheduled_work(); + + /* * Shutdown the current line discipline, and reset it to N_TTY. * N.B. why reset ldisc when we're releasing the memory?? */ @@ -1282,18 +1294,6 @@ static void release_dev(struct file * fi module_put(o_tty->ldisc.owner); o_tty->ldisc = ldiscs[N_TTY]; } - - /* - * Prevent flush_to_ldisc() from rescheduling the work for later. Then - * kill any delayed work. - */ - clear_bit(TTY_DONT_FLIP, &tty->flags); - cancel_delayed_work(&tty->flip.work); - - /* - * Wait for ->hangup_work and ->flip.work handlers to terminate - */ - flush_scheduled_work(); /* * The release_mem function takes care of the details of clearing _