Race condition between destructor of an object inheriting from qobject and direct connection signal
-
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 -
Hi,
did you try the deleteLater option? Then the object will be deleted (destructor called) when the eventqueue is empty. -
The problem is that this is a direct call so it's not entered into the event queue.
-
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.
-
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. -
Have you estimated if the overhead of queued connections is big enough? May be it's not worth the hassle.
-
It definitely worth it for me. does anyone know of a mechanism available by qt for this kind of situation?
thanks -
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.
-
[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. -
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...
-
I think that Qt's way of neater solution IS queued connections. Direct connections are not thread-safe by design.