macOS: Don't leak QEventDispatcherUNIX during event dispatcher creation
During QCoreApplication initialization, we create the main thread's event dispatcher, which for a GUI app happens via QGuiApplicationPrivate's createEventDispatcher() override. This in turn relies on the platform integration to create the event dispatcher, but to do that it needs to create the platform integration first. And this might result in calling APIs that themselves initialize the main thread event dispatcher, such as QEventLoop, which non-lazily creates an event dispatcher for the thread. We already had a check to catch the platform integration setting the QCoreApplictionPrivate::eventDispatcher member, but not anything for checking the current thread data. On macOS this resulted in a leak of QEventDispatcherUNIX because QCocoaDrag contained a QEventLoop member. We now track the event loop temproarily via a pointer instead, like we do in other places. An alternative fix would be to defer the initialization of QCocoaDrag until QCocoaIntegration::drag() is called, but that would run the risk of something calling the function during platform initialization and we'd be back to the same problem. It's unclear why QEventLoop is not lazily ensuring the event dispatcher, and this might be a wider fix for similar issues. Change-Id: I643010ddb09945936ce9b0b94de0df96f6fe218f Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> (cherry picked from commit 41608170502a08b054a7a244034334d9f4c9ba11) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
9244018577
commit
8a35934362
@ -1523,7 +1523,11 @@ void QGuiApplicationPrivate::createEventDispatcher()
|
||||
if (platform_integration == nullptr)
|
||||
createPlatformIntegration();
|
||||
|
||||
// The platform integration should not mess with the event dispatcher
|
||||
// The platform integration should not result in creating an event dispatcher
|
||||
Q_ASSERT_X(!threadData.loadRelaxed()->eventDispatcher, "QGuiApplication",
|
||||
"Creating the platform integration resulted in creating an event dispatcher");
|
||||
|
||||
// Nor should it mess with the QCoreApplication's event dispatcher
|
||||
Q_ASSERT(!eventDispatcher);
|
||||
|
||||
eventDispatcher = platform_integration->createEventDispatcher();
|
||||
|
@ -44,7 +44,7 @@ private:
|
||||
NSEvent *m_lastEvent;
|
||||
NSView *m_lastView;
|
||||
Qt::DropAction m_executed_drop_action;
|
||||
QEventLoop internalDragLoop;
|
||||
QEventLoop *m_internalDragLoop = nullptr;
|
||||
|
||||
bool maybeDragMultipleItems();
|
||||
|
||||
|
@ -213,7 +213,9 @@ bool QCocoaDrag::maybeDragMultipleItems()
|
||||
}
|
||||
|
||||
[sourceView beginDraggingSessionWithItems:dragItems event:m_lastEvent source:sourceView];
|
||||
internalDragLoop.exec();
|
||||
QEventLoop eventLoop;
|
||||
QScopedValueRollback updateGuard(m_internalDragLoop, &eventLoop);
|
||||
eventLoop.exec();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -224,8 +226,9 @@ void QCocoaDrag::setAcceptedAction(Qt::DropAction act)
|
||||
|
||||
void QCocoaDrag::exitDragLoop()
|
||||
{
|
||||
if (internalDragLoop.isRunning())
|
||||
internalDragLoop.exit();
|
||||
Q_ASSERT(m_internalDragLoop);
|
||||
if (m_internalDragLoop->isRunning())
|
||||
m_internalDragLoop->exit();
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user