QMetaCallEvent in multithreading application
-
Hi there,
We have an application that is running GUI in the main thread T1 and there are other threads T2-Tx that are making calls to objects in T1 thread.
@class QMyApp : public QApplication
{
...
}
@T1 is running event loop:
@bool QApplication::notify(QObject* receiver, QEvent* event)
{
try
{
return QApplication::notify(receiver, event);
}
catch (std::exception& exception)
{
qFatal("Error '%s' sending event '%s' to object '%s' ('%s').", exception.what(), typeid(*event).name(), qPrintable(receiver->objectName()), typeid(*receiver).name());
throw;
}
catch (...)
{
qFatal("Error <unknown> sending event '%s' to object '%s' ('%s').", typeid(*event).name(), qPrintable(receiver->objectName()), typeid(*receiver).name());
throw;
}
return false;
}@T2 is sending event to T1:
QMetaObject::invokeMethod(obj, member, Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, result), Q_ARG(QString, qParam1), Q_ARG(QString, qParam2), Q_ARG(QString, qParam3));
T2 waits while T1 processes the event and returns the response.
The issues is that sometimes we have AV exception in QApplication::notify() method (I think because sometimes receiver is dead ath the moment of event processing). So, T1 caught an exception and tries to close application with qFatal, but T2 is waiting when QMetaCallEvent will be destroyed (and QSemaphore will be released). Is it okay to destroy event manually (delete event) in catch block?
The goal is to close application and avoid hangs.
-
I think you have a design problem.
You must ensure that T2 is not sending requests to T1 anymore when you destroy it. I think the simplest solution for you would be to simply use signals and slots for communication between T2 and T1 as what happens in the background is pretty much what you are doing by hand.
However, the signal/slot mechanism provides extra security in the sense that when one object is destroyed (using deleteLater()) all its pending events are processed and all its signals/slots are cleanly disconnected. -
Thank you for your response! We definitely have problem with architecture there. We are looking for appropriate solution. But as temporary hack -- it seems it's okay to destroy QMetaCallEvent in the catch block.
[quote author="rcari" date="1349775603"]I think you have a design problem.
You must ensure that T2 is not sending requests to T1 anymore when you destroy it. I think the simplest solution for you would be to simply use signals and slots for communication between T2 and T1 as what happens in the background is pretty much what you are doing by hand.
However, the signal/slot mechanism provides extra security in the sense that when one object is destroyed (using deleteLater()) all its pending events are processed and all its signals/slots are cleanly disconnected.[/quote]