[Development] invokeMethod() with function pointers

Thiago Macieira thiago.macieira at intel.com
Sat Jan 21 00:20:53 CET 2017


On sexta-feira, 20 de janeiro de 2017 17:34:50 PST Grégoire Barbier wrote:
> > See the discussion in https://codereview.qt-project.org/83404/ for why
> > this is not a good idea.
> > In summary, BlockingQueuedConnection is dangerous as it can lead to
> > deadlock if the other thread is waiting on your thread. In order to use
> > it properly, you really need to know, while programming in which thread
> > you are and which thread you try to communicate to, and be sure that
> > there is never in your program cases where the other thread may be
> > waiting on a QWaitCondition for your other thread. So this pattern with
> > QThread::currentThread() == this-> 
> >>thread() before a BlockingQueuedConnection is really dangerous.

> I respect the fact that you rejected Qt::BlockingAutoConnection in 2014
> because of its potential danger, but I'm not sure that it's better to
> let people use the "QThread::currentThread() == this" pattern without
> being warned rather than implementing Qt::BlockingAutoConnection, with a
> detailed warning in the doc.

It's a shift of responsibility. If we had the BlockingAutoConnection (or 
SynchronousConnection, which is what I wanted to call it during Qt 4.5 when I 
first proposed it), the deadlock would be Qt's fault. Since it's you doing 
that, the deadlock becomes your fault and you're the one who needs to fix it.

> Moreover, I don't understand whi BlockingAutoConnection would be more
> dangerous (if it were to be added) than BlockingQueuedConnection is
> currently already dangerous.

Think about this: QueuedConnection and BlockingQueuedConnection chase the 
target object across moveToThreads. That is, if thread A is doing 
invokeMethod() while thread B does obj->moveToThread(C), then the invocation 
chases obj to thread C. That's a good thing.

But what happens if it got moved to thread A? Since thread A is blocked on a 
semaphore wait, it can't handle the incoming metacall event. That's a 
deadlock.

What's more, we can't solve it: even if we could detect the deadlock formation 
before it happens (and I'm not sure we can), we'd need to pick the metacall 
event out of the event queue, which means it could jump the queue and things 
would execute in the wrong order. So, no, it's impossible to implement 
BlockingAutoConnection so long as the object can be moved back to the calling 
thread.

> With your own words from 2014:
> 
> """
> I would not even try to solve this race with moveToThead, as a mention,
> i think we just need to document that one must not call moveToThread
> when Blocking connecitona re involved.
> """
> 
> Maybe it would be interesting to set this comment in enum
> Qt::ConnectionType doc, just right to Qt::BlockingQueuedConnection (or a
> would-be Qt::BlockingAutoConnection) and not only in the "Signals and
> Slots Across Threads" paragraph, to make everything safer with noobs
> (like me) that do not read the whole docs but only spam the F1 key from
> with Qt Creator.

Adding the warning to BlockingQueuedConnection is a good idea.

> > On the other hand, it would be useful to get the return value of a
> > QueuedConnection in a QFuture.

That's no different than a QueuedConnection with a posted event back with the 
result. In fact, we have a very good implementation for "post event back with 
result": we call it a "signal-slot connection".

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center




More information about the Development mailing list