-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
6.8.2, 6.9.2
-
None
-
Users are on a variety of systems, Win10/11, AMD, INTEL, NVIDIA
-
-
8f4430a21 (dev), 48599fd40 (6.10), 512791d1d (6.9), 6cca1cc08 (tqtc/lts-6.8)
For a while already I can see in my apps crash reporting that one of the main crashes we experience comes from the Qt rendering layer.
For better interoperability with Qt WebEngine within the app, we enabled Direct3d11 RHI for both Qt Quick and Qt Widgets. This usually works without any issues, however we can see these sporadic crashes in the window backing store. Unfortunately we cannot reproduce the issue locally, but following the backtrace reveals an unchecked pointer usage in `QBackingStoreDefaultCompositor::flush` is used unchecked, but can be nullptr.
Here is the backtrace (using Qt 6.8.2):
OS Version: Windows 10.0.19045 (6216) Report Version: 104 Crashed Thread: 19648 Application Specific Information: Fatal Error: EXCEPTION_ACCESS_VIOLATION_READ / 0x0 Thread 19648 Crashed: 0 Qt6Gui.dll 0x7ffcbf41523c QBackingStoreDefaultCompositor::flush (qbackingstoredefaultcompositor.cpp:486) 1 Qt6Gui.dll 0x7ffcbf532dcf QPlatformBackingStore::rhiFlush (qplatformbackingstore.cpp:219) 2 Qt6Widgets.dll 0x7ffcbfc747ff QWidgetRepaintManager::flush (qwidgetrepaintmanager.cpp:1068) 3 Qt6Widgets.dll 0x7ffcbfc74b35 QWidgetRepaintManager::flush (qwidgetrepaintmanager.cpp:980) 4 Qt6Widgets.dll 0x7ffcbfc77813 QWidgetRepaintManager::paintAndFlush (qwidgetrepaintmanager.cpp:912) 5 Qt6Widgets.dll 0x7ffcbfc786ef QWidgetRepaintManager::sync (qwidgetrepaintmanager.cpp:632) 6 Qt6Widgets.dll 0x7ffcbfc7b15d QWidgetWindow::handleExposeEvent (qwidgetwindow.cpp:1065) 7 Qt6Widgets.dll 0x7ffcbfc79ab6 QWidgetWindow::event (qwidgetwindow.cpp:346) 8 Qt6Widgets.dll 0x7ffcbfc134c1 QApplicationPrivate::notify_helper (qapplication.cpp:3296) 9 Qt6Widgets.dll 0x7ffcbfc125f5 QApplication::notify (qapplication.cpp:3250) 10 Qt6Core.dll 0x7ffcbedd313e QCoreApplication::notifyInternal2 (qcoreapplication.cpp:1172) 11 Qt6Gui.dll 0x7ffcbf3a7088 QGuiApplicationPrivate::processExposeEvent (qguiapplication.cpp:3464) 12 Qt6Gui.dll 0x7ffcbf40427a QWindowSystemInterface::sendWindowSystemEvents (qwindowsysteminterface.cpp:1113) 13 Qt6Gui.dll 0x7ffcbf400e03 QWindowSystemInterface::flushWindowSystemEvents (qwindowsysteminterface.cpp:1082) 14 qwindows.dll 0x7ffcbe651289 QWindowsWindow::handleWmPaint (qwindowswindow.cpp:2437) 15 qwindows.dll 0x7ffcbe5fa949 QWindowsContext::windowsProc (qwindowscontext.cpp:1174) 16 qwindows.dll 0x7ffcbe5fb6f4 qWindowsWndProc (qwindowscontext.cpp:1499) 17 USER32.dll 0x7ffd4eb4ef5b UserCallWinProcCheckWow 18 USER32.dll 0x7ffd4eb4e8cb DispatchClientMessage 19 USER32.dll 0x7ffd4eb610c2 _fnDWORD 20 ntdll.dll 0x7ffd4f891373 KiUserCallbackDispatch 21 win32u.dll 0x7ffd4d7e1703 ZwUserDispatchMessage 22 USER32.dll 0x7ffd4eb4e7b0 DispatchMessageWorker 23 Qt6Core.dll 0x7ffcbef5efd3 QEventDispatcherWin32::processEvents (qeventdispatcher_win.cpp:537) 24 Qt6Gui.dll 0x7ffcbf6b7de8 QWindowsGuiEventDispatcher::processEvents (qwindowsguieventdispatcher.cpp:36) 25 Qt6Core.dll 0x7ffcbedd9c43 [inlined] QEventLoop::processEvents (qeventloop.cpp:103) 26 Qt6Core.dll 0x7ffcbedd9c43 QEventLoop::exec (qeventloop.cpp:185) 27 Qt6Core.dll 0x7ffcbedd1641 QCoreApplication::exec (qcoreapplication.cpp:1515) [external]
Crash Analysis
1. Call origin
- The crash occurs inside QBackingStoreDefaultCompositor::flush().
- At line 486, the code assumes that a valid swapchain object is present.
2. Swapchain retrieval
- QPlatformBackingStore::rhiFlush() requests a swapchain via surfaceSupport.rhiSupport.swapChainForWindow(window);
3. Failure branch in swapChainForWindow
- QBackingStoreRhiSupport::swapChainForWindow() is responsible for constructing or resizing the swapchain.
- If swapchain->createOrResize() fails, the function explicitly returns nullptr.
4. Unchecked dereference
- QBackingStoreDefaultCompositor::flush() does not validate the return value.
- It proceeds to dereference the swapchain pointer, which in this case is nullptr.
Notes
I understand that the swapchain creation is a deep platform specific integration and it is expected that the creation or resizing can fail. Therefore I believe the QBackingStoreDefaultCompositor::flush should check if the swapchain object is valid and return QPlatformBackingStore::FlushFailed if not instead of unconditionally use it.
However, I don't know if there are deeper consequence of a failing flush for the app / window / lifecycle. Therefore some Qt / RHI expert would be required to check and evaluate the consequences of such an early return.
For Gerrit Dashboard: QTBUG-139994 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
674429,2 | Bail out on null swapchain in rhi flush | dev | qt/qtbase | Status: MERGED | +2 | 0 |
676660,2 | Bail out on null swapchain in rhi flush | 6.10 | qt/qtbase | Status: MERGED | +2 | 0 |
676787,2 | Bail out on null swapchain in rhi flush | 6.9 | qt/qtbase | Status: MERGED | +2 | 0 |
676897,2 | Bail out on null swapchain in rhi flush | tqtc/lts-6.8 | qt/tqtc-qtbase | Status: MERGED | +2 | 0 |