Commit d1e40344 authored by Daniel Vrátil's avatar Daniel Vrátil 🤖

Fix SessionThread dtor timeout when destroying default Session

The default Session does not have any owner and is managed by QThreadStorage,
so it is only destroyed when QApplication is being destroyed. Because at
this point event loop is no longer running, SessionThread::doThreadQuit()
is not invoked from SessionThread dtor and we hit the 10 seconds timeout.

This affects especially unit-test which take less than second to execute,
but then get stuck for 10 seconds in the SessionThread dtor during
clean up.

Since the new code relies on QCoreApplication::aboutToQuit() to destroy
the default Sessions while qApp is still running we had to adjust
AKONADITEST_MAIN() a little to start the QApplication event loop, because
otherwise the signal is not emitted.
parent 0d8adb44
......@@ -25,6 +25,7 @@
#include <QtTest/QTest>
#include <QtTest/QSignalSpy>
#include <QtCore/QTimer>
/**
* \short Akonadi Replacement for QTEST_MAIN from QTestLib
......@@ -33,6 +34,10 @@
* So instead of writing QTEST_MAIN( TestClass ) you write
* QTEST_AKONADIMAIN( TestClass ).
*
* Unlike QTEST_MAIN, this macro actually does call QApplication::exec() so
* that the application is running during test execution. This is needed
* for proper clean up of Sessions.
*
* \param TestObject The class you use for testing.
*
* \see QTestLib
......@@ -49,8 +54,14 @@
app.setOrganizationName(QLatin1String("KDE")); \
QGuiApplication::setQuitOnLastWindowClosed(false); \
qRegisterMetaType<QList<QUrl>>(); \
TestObject tc; \
return QTest::qExec( &tc, argc, argv ); \
int result = 0; \
QTimer::singleShot(0, [argc, argv, &result]() { \
TestObject tc; \
result = QTest::qExec(&tc, argc, argv); \
qApp->quit(); \
}); \
app.exec(); \
return result; \
}
namespace AkonadiTest
......
......@@ -383,7 +383,14 @@ void SessionPrivate::createDefaultSession(const QByteArray &sessionId)
Q_ASSERT_X(!instances()->hasLocalData(), "SessionPrivate::createDefaultSession",
"You tried to create a default session twice!");
instances()->setLocalData(new Session(sessionId));
Session *session = new Session(sessionId);
session->connect(qApp, &QCoreApplication::aboutToQuit,
[]() {
// We must destroy Session while QApplication is still
// running otherwise deleting SessionThread will deadlock
instances()->setLocalData(Q_NULLPTR);
});
instances()->setLocalData(session);
}
void SessionPrivate::setDefaultSession(Session *session)
......@@ -394,7 +401,12 @@ void SessionPrivate::setDefaultSession(Session *session)
Session *Session::defaultSession()
{
if (!instances()->hasLocalData()) {
instances()->setLocalData(new Session());
Session *session = new Session();
session->connect(qApp, &QCoreApplication::aboutToQuit,
[]() {
instances()->setLocalData(Q_NULLPTR);
});
instances()->setLocalData(session);
}
return instances()->localData();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment