Commit e829d2e4 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Fix race on tty close

From: Benjamin Herrenschmidt <benh@kernel.crashing.org>

ldisc close can race with the flush_to_ldisc workqueue.

This patch fixes it by killing the workqueue first.
parent 19e12876
...@@ -1266,6 +1266,18 @@ static void release_dev(struct file * filp) ...@@ -1266,6 +1266,18 @@ static void release_dev(struct file * filp)
printk(KERN_DEBUG "freeing tty structure..."); printk(KERN_DEBUG "freeing tty structure...");
#endif #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. * Shutdown the current line discipline, and reset it to N_TTY.
* N.B. why reset ldisc when we're releasing the memory?? * N.B. why reset ldisc when we're releasing the memory??
...@@ -1282,18 +1294,6 @@ static void release_dev(struct file * filp) ...@@ -1282,18 +1294,6 @@ static void release_dev(struct file * filp)
module_put(o_tty->ldisc.owner); module_put(o_tty->ldisc.owner);
o_tty->ldisc = ldiscs[N_TTY]; 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 * The release_mem function takes care of the details of clearing
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment