From d909a8ed67780412ca20d120160ddb8e5f70c23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 14 Dec 2023 15:16:40 +0100 Subject: [PATCH] Document how to process deferred deletes in a plugin-scenario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When Qt is not driving the event dispatching, the event loop level of the thread will stay 0. As a result, we will not automatically bump the deferred delete event's scope level to 1 when the deferred delete happens from a code path that doesn't raise the scope level via QScopedScopeLevelCounter, leaving the event with loop and scope level 0. As we only process these 0+0 deferred delete events automatically from QCoreApplicationPrivate::execCleanup(), which is not going to be called when the app doesn't call QCoreAppliction::exec(), we were failing to process the deferred deletes both during the application's runtime, as well as on shutdown. Task-number: QTBUG-120124 Fixes: QTBUG-117975 Pick-to: 6.5 Change-Id: I2b8accb432517a48370923ee2d760f8e2e4a8055 Reviewed-by: Fabian Kosmale (cherry picked from commit 7fac2fac9a512cef2d5cdefd9837d76f8be7de05) Reviewed-by: Tor Arne Vestbø --- src/corelib/kernel/qobject.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 27d719519ae..98f3e8f345e 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2394,6 +2394,21 @@ void QObject::removeEventFilter(QObject *obj) event loop was still running: the Qt event loop will delete those objects as soon as the new nested event loop starts. + In situations where Qt is not driving the event dispatcher via e.g. + QCoreApplication::exec() or QEventLoop::exec(), deferred deletes + will not be processed automatically. To ensure deferred deletion in + this scenario, the following workaround can be used: + + \code + const auto *eventDispatcher = QThread::currentThread()->eventDispatcher(); + QObject::connect(eventDispatcher, &QAbstractEventDispatcher::aboutToBlock, + QThread::currentThread(), []{ + if (QThread::currentThread()->loopLevel() == 0) + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + } + ); + \endcode + \note It is safe to call this function more than once; when the first deferred deletion event is delivered, any pending events for the object are removed from the event queue.