Messages in this thread | | | Date | Mon, 7 Nov 2011 13:06:43 +0000 | From | Alan Cox <> | Subject | Re: PROBLEM: Race condition in tty buffer's function flush_to_ldisc(). |
| |
> if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) { > ..... > } else > prink... > In my syslog appear this prink on pty devices.
Then we need to understand the call paths that did this. I suspect it may be a bug in the hacks Linus made to n_tty. They've always bothered me as they never looked correct.
Can you get traces to see if it is actually calling flush_to_ldisc multithreaded on a given tty
> Why we need: "if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {" > if flush_to_ldisc is single threaded? > we can: set_bit(TTY_FLUSHING, &tty->flags) > without if() at all.
It is single threaded with respect to itself (you can't have two flush_to_ldisc on the same tty at once) but you can have a parallel call to tty_buffer_flush. The tty_buffer_flush path needs to pick the right approach reliably.
So the theory is
If TTY_FLUSHING is set then tty_buffer_flush lets the flush_to_ldisc do the work. During this time we won't fluish a buffer under the ldisc.
If TTY_FLUSHING is not set then we will do the flush directly. As we hold tty->buf.lock at that point the two cannot race as far as I can see.
We are actually now probably at the point we could take a per tty mutex on the flush_to_ldisc and use it to tidy up ldisc change, flush and other things. So this code could welll be something worth simplifying once the rest of the tty_lock() is cleaned out.
Alan
| |