Race condition between destructor of an object inheriting from qobject and direct connection signal
-
wrote on 1 Oct 2014, 11:49 last edited by
Hi.
I've got three objects A,B,C which inherit from QObject.
A,B run in the context of two different threads.
C is a member of A.
B has a signal connected to a slot of C using a DirectConnection.
now when the thread containing A goes down, A and C are destroyed.
The problem is that there is a race condition between the destructor of C and the directConnection slot of C, which causes a crash.
Is there any mechanism provided by qt that may solve this problem, namely I want C's slots to disconnect as soon as I enter C's destructor.thanks
Ilya -
wrote on 1 Oct 2014, 12:16 last edited by
Hi,
did you try the deleteLater option? Then the object will be deleted (destructor called) when the eventqueue is empty. -
wrote on 1 Oct 2014, 12:19 last edited by
The problem is that this is a direct call so it's not entered into the event queue.
-
wrote on 1 Oct 2014, 13:06 last edited by
What do you mean, direct call? You shouldn't cross connect threads. Or you should create a signal/slot connection between B and C that is send when C is deleted it will call B to stop calling the other thread class.
-
wrote on 1 Oct 2014, 13:33 last edited by
I want to avoid the overhead of a queuedConnection.
I incorporate the use of locks to avoid race conditions, yet, those locks don't help me with this situation. -
wrote on 1 Oct 2014, 13:45 last edited by
Have you estimated if the overhead of queued connections is big enough? May be it's not worth the hassle.
-
wrote on 1 Oct 2014, 14:32 last edited by
It definitely worth it for me. does anyone know of a mechanism available by qt for this kind of situation?
thanks -
wrote on 1 Oct 2014, 14:45 last edited by
Consider thread B has just called the slot. Then it is preempted, and thread A/C executes. The objects are destroyed. But thread B is already executing the slot, and the crash is unavoidable.
The only way I can imagine is to lock the object before signal emission in thread B, to prevent thread A/C from running until the slot is complete. But the simplicity of this solution is questionable.
-
Hi,
If you use a direct connection, then C's slot runs in B's thread. Are you sure that's what you want?
If you want signals and slots across threads, you must use a queued connection; if the overhead of a queued connection is too high, don't use signals and slots to communicate between your threads.
-
wrote on 1 Oct 2014, 14:53 last edited by
[quote author="JKSH" date="1412174763"]Hi,
If you use a direct connection, then C's slot runs in B's thread. Are you sure that's what you want?
If you want signals and slots across threads, you must use a queued connection; if the overhead of a queued connection is too high, don't use signals and slots to communicate between your threads.[/quote]
I second this. Signals and slots are the way to use the objects thread-safely. If you do not use queued connections, then you must implement your own mechanism of thread safety. -
wrote on 1 Oct 2014, 15:06 last edited by
Hi.
thanks you for your answers, I already have a solution which involves a mutex, such that the mutex's owner is the main thread and it passes it to the C object. That way the mutex would still exist even after C is destroyed and so can be used safely. So I combine it with a boolean passed to it from the main thread, such that the boolean lives in the main thread and again will not be destroyed in C's destructor.C changes it's value once the destructor is called and the slot verifies it's state and if true exits.The mutex is used in order to provide mutual exclusion for this boolean. This solution would solve this scenario.
But what I wish to know is whether qt provides a neater solution for this scenario (using the directConnection).
So if anyone knows any such built in mechanism I would be more than grateful...
-
wrote on 2 Oct 2014, 07:59 last edited by
I think that Qt's way of neater solution IS queued connections. Direct connections are not thread-safe by design.
1/12