In the case when we use co_await qCoro(obj, &Obj::signal, timeout) when obj was moved to another thread and the await results in a timeout, the application crashes with a bunch of warnings, such as:
QObject::setParent: Cannot set parent, new parent is in a different thread
QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
QBasicTimer::start: Timers cannot be started from another thread
Example for reproduction
Here is a minimalish Qt5 example (I tried to make a simple console example, but it doesn't behave as I expect, so I had to complicate it a bit with GUI, but now it resembles my original problem pretty well):
After one second warning dialog will pop up and crash the application.
In the log there will be no Timeout!, but instead some warnings from Qt.
The QMessageBox is vital here, and that's the part I am not entirely sure why, perhaps because it spins a new event loop and pauses the previous one? If we remove it, or remove the moveToThread - everything works as expected.
Here the mObj is the receiver, while mTimeoutTimer is the emitter and Qt::AutoConnection is used by default. In the situation that mObj is in different thread, the slot is executed via Qt::QueuedConnection - on the receiver's thread and the coroutine will be resumed from different thread than the one coroutine was lauched in. That said I'm not very skilled in coroutines at the moment, so I might be wrong.
Description:
In the case when we use
co_await qCoro(obj, &Obj::signal, timeout)
whenobj
was moved to another thread and the await results in a timeout, the application crashes with a bunch of warnings, such as:Example for reproduction
Here is a minimalish Qt5 example (I tried to make a simple console example, but it doesn't behave as I expect, so I had to complicate it a bit with GUI, but now it resembles my original problem pretty well):
After running it the following will happen:
Timeout!
, but instead some warnings from Qt.The
QMessageBox
is vital here, and that's the part I am not entirely sure why, perhaps because it spins a new event loop and pauses the previous one? If we remove it, or remove themoveToThread
- everything works as expected.Potential cause
Reviewing the code, I see that the following might be the cause: https://github.com/danvratil/qcoro/blob/0006e41682a24b78a1dafe41a6e233a23ce16cea/qcoro/core/qcorosignal.h#L111-L120
Here the
mObj
is the receiver, whilemTimeoutTimer
is the emitter andQt::AutoConnection
is used by default. In the situation thatmObj
is in different thread, the slot is executed viaQt::QueuedConnection
- on the receiver's thread and the coroutine will be resumed from different thread than the one coroutine was lauched in. That said I'm not very skilled in coroutines at the moment, so I might be wrong.