diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2023-12-14 14:34:14 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2023-12-15 11:46:15 +0100 |
commit | f762e9b646e240d9e8d3d7de928ae1333227c8a0 (patch) | |
tree | c11350563df463a369cb7aa287fa275e696b46a0 | |
parent | 35f853837793b6d526815140021013cf03cc80b5 (diff) |
Bluetooth Windows: fix segfault in COM de-init
While doing COM initialization/deinitialization, we always implicitly
assumed that QCoreApplication instance is available.
However, if the Bluetooth objects are re-parented to the main
application, the QCoreApplication instance will already be removed by
the time we want to delete the Bluetooth object (and call COM de-init).
Fix it by caching the main application's thread, and using it instead
of QCoreApplication::instance()->thread() in the mainThreadCoUninit()
helper method.
This commit still assumes that all Bluetooth objects are created
*after* the main QCoreApplication instance.
Amends 340b84a5578f78d7a399e369e900ac991d9e0da2.
Fixes: QTBUG-119063
Pick-to: 6.7 6.6 6.5 6.2
Change-Id: I450e4e14039ca27fcfd1f3f131789b049e1edb03
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r-- | src/bluetooth/qbluetoothutils_winrt.cpp | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/src/bluetooth/qbluetoothutils_winrt.cpp b/src/bluetooth/qbluetoothutils_winrt.cpp index ca4326f8..b146be19 100644 --- a/src/bluetooth/qbluetoothutils_winrt.cpp +++ b/src/bluetooth/qbluetoothutils_winrt.cpp @@ -43,6 +43,7 @@ QByteArray byteArrayFromBuffer(const ComPtr<NativeBuffer> &buffer, bool isWCharS } static QSet<void*> successfulInits; +static QThread *mainThread = nullptr; void mainThreadCoInit(void* caller) { @@ -58,27 +59,33 @@ void mainThreadCoInit(void* caller) return; } + Q_ASSERT_X(!mainThread || mainThread == QThread::currentThread(), + __FUNCTION__, "QCoreApplication's thread has changed!"); + // This executes in main thread which may run Gui => use apartment threaded if (!SUCCEEDED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { qCWarning(QT_BT_WINDOWS) << "Unexpected COM initialization result"; return; } successfulInits.insert(caller); + if (!mainThread) + mainThread = QThread::currentThread(); } void mainThreadCoUninit(void* caller) { Q_ASSERT(caller); - if (QThread::currentThread() != QCoreApplication::instance()->thread()) { - qCWarning(QT_BT_WINDOWS) << "Main thread COM uninit tried from another thread"; + if (!successfulInits.contains(caller)) { + qCWarning(QT_BT_WINDOWS) << "COM uninitialization without initialization"; return; } - if (!successfulInits.contains(caller)) { - qCWarning(QT_BT_WINDOWS) << "COM uninitialization without initialization"; + if (QThread::currentThread() != mainThread) { + qCWarning(QT_BT_WINDOWS) << "Main thread COM uninit tried from another thread"; return; } + CoUninitialize(); successfulInits.remove(caller); |