Re: tty: deadlock between n_tracerouter_receivebuf and flush_to_ldisc

From: One Thousand Gnomes
Date: Wed Jan 20 2016 - 09:59:42 EST


> I read that, I didn't understand it. Which link is wrong and why?
>
> > And I don't understand how the following is a deadlock, since there is
> > no cycle...
> >
> > Possible unsafe locking scenario:
> > CPU0 CPU1
> > ---- ----
> > lock(&buf->lock);
> > lock(&o_tty->termios_rwsem/1);
> > lock(&buf->lock);
> > lock(routelock);
>
> Ignore the stupid picture, it only really works for simple cases.

There are two line disciplines using two different locking orders

The two line disciplines never execute at once. A given tty is either
using one or the other and there is a clear and correctly locked
changeover.


semantically its something a bit like


foo(x)
{
if (x == 1) {
lock(A)
lock(B)
} else {
lock(B)
lock(A)
}

Do stuff();

if (x == 1) {
unlock(B)
unlock(A)
} else {
unlock(A)
unlock(B)
}
}

with the guarantee made elsewhere that no instances of foo(1) and foo(0)
are ever executing at the same time.

That's not by dumb design - it's an interesting "nobody ever noticed
this" turned up by the lock detector between two totaly unrelated bits of
code.

Alan