summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Weimer <bernd.weimer@pelagicore.com>2020-07-28 17:53:14 +0200
committerBernd Weimer <bernd.weimer@pelagicore.com>2020-08-03 14:05:16 +0200
commit6acc459d797b2238d7aafc10dc8f405d90b940eb (patch)
tree02cc607cd5a6fa291aff28458f48a290ad86478d
parent7038e1681863c8a59c6c6a758fc7ec41f29f2be7 (diff)
downloadqtapplicationmanager-6acc459d797b2238d7aafc10dc8f405d90b940eb.tar.gz
Fix potential crash when a window is released
There can be a race condition when a window is released. A crash happens very rarely in the windowitem2 QML test case (~1%), but could be seen more often in more complex code. Because, both window->deleteLater() and isBeingDisplayedChanged are processed asynchronously, the former might run before the latter and hence the window might already be destructed when used in the isBeingDisplayedChanged handler. Cherry-picked from 5.15: 520d102 Change-Id: Iddb687f057666ef3d34feb6472d3ba2171093d91 Reviewed-by: Robert Griebl <robert.griebl@qt.io>
-rw-r--r--src/window-lib/windowmanager.cpp12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/window-lib/windowmanager.cpp b/src/window-lib/windowmanager.cpp
index 97a3b68c..b361609a 100644
--- a/src/window-lib/windowmanager.cpp
+++ b/src/window-lib/windowmanager.cpp
@@ -633,10 +633,14 @@ void WindowManager::setupWindow(Window *window)
emit windowPropertyChanged(win, name, value);
});
- connect(window, &Window::isBeingDisplayedChanged, this, [this, window]() {
- if (window->contentState() == Window::NoSurface && !window->isBeingDisplayed()) {
- removeWindow(window);
- releaseWindow(window);
+ // In very rare cases window->deleteLater() is processed before the isBeingDisplayedChanged
+ // handler below, i.e. the window destructor runs before the handler.
+ QPointer<Window> guardedWindow = window;
+ connect(window, &Window::isBeingDisplayedChanged, this, [this, guardedWindow]() {
+ if (!guardedWindow.isNull() && guardedWindow->contentState() == Window::NoSurface
+ && !guardedWindow->isBeingDisplayed()) {
+ removeWindow(guardedWindow);
+ releaseWindow(guardedWindow);
}
}, Qt::QueuedConnection);