From 0270651dda8e247164a8dccd71fb65712c7d1480 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Fri, 25 Aug 2017 16:06:44 +0200 Subject: Cocoa integration: do not use released session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QTBUG_10735_crashWithDialog started to show flakyness recently - it crashes, but not every time (which fits the definition of UB perfectly). While the test itself is doing weird things and puts our event dispatcher into a weird state, our API allows to: 1. Using QDialog to enter event loop (with runModalSession under the hood), then ... 2. to call from a slot (e.g. timer-attached) QApplication::closeAllWindows() while ... 3. we are still inside that special loop and using the 'session' object, thus ... 4. on the next iteration with [NSApp runModalSession:session] we'll re-use already released session (released by endModalSession which in turn was called indirectly by closeAllWindows). And Cocoa gives us a warning/hint: "Use of freed session detected. Do not call runModalSession: after calling endModalSesion:." Task-number: QTBUG-62589 Change-Id: Ie651cee1fba43cfd2b0fc44af5eddc5fd52e2907 Reviewed-by: Tor Arne Vestbø Reviewed-by: Morten Johan Sørvig Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm') diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index d2f985ec87..b22f1b1f54 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -401,8 +401,18 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags) // [NSApp run], which is the normal code path for cocoa applications. if (NSModalSession session = d->currentModalSession()) { QBoolBlocker execGuard(d->currentExecIsNSAppRun, false); - while ([NSApp runModalSession:session] == NSModalResponseContinue && !d->interrupt) + while ([NSApp runModalSession:session] == NSModalResponseContinue && !d->interrupt) { qt_mac_waitForMoreEvents(NSModalPanelRunLoopMode); + if (session != d->currentModalSessionCached) { + // It's possible to release the current modal session + // while we are in this loop, for example, by closing all + // windows from a slot via QApplication::closeAllWindows. + // In this case we cannot use 'session' anymore. A warning + // from Cocoa is: "Use of freed session detected. Do not + // call runModalSession: after calling endModalSesion:." + break; + } + } if (!d->interrupt && session == d->currentModalSessionCached) { // Someone called [NSApp stopModal:] from outside the event -- cgit v1.2.3