The worst signal safety bug
Suppose you want to change a QObject’s thread affinity with moveToThread(). Of course, you need to be mindful of what your object is doing, how it is parented, what it is interacting with, etc, to use moveToThread() properly; it is certainly an advanced function. However, there’s a “gotcha” that might not be immediately apparent, which is that you have to be even more careful if you want to use moveToThread() on an object that isn’t signal safe (SS). Why? Let’s do an example.
Here we have class Foo, which emits stuffDone() at some point. The Bar class is listening for this signal, and will move Foo into another thread once the signal is received.
void Foo::doStuff()
{
[...]
emit stuffDone();
[... more code ...]
}
void Bar::foo_stuffDone()
{
foo->moveToThread(otherThread);
}
The problem is that the code following the signal emit will be executed from the object’s original thread and not from the thread that the object has been moved to. Even if the object isn’t doing anything in the new thread, it may still be illegal to use certain calls from the original thread. For example, if Foo had child timer or socket objects, and these got moved into the new thread, then any calls to these objects from the original thread would be major fail.
Anyway, there isn’t anything new to teach here. If you don’t know the SS compliancy of an object, then you can’t do anything with it if one of its signals might be on the call stack. It’s that simple, and moveToThread() should not be treated any more or less specially than other member functions. What’s interesting about moveToThread() are the disastrous results you can get.
