diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2021-11-25 18:22:14 +0100 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2021-11-26 09:30:17 +0100 |
commit | 978dbaa9e975968dd6bacf36f70238c9b61643b4 (patch) | |
tree | 26143ccb4c5eea96f1b52735256c215e37d6932a | |
parent | 1e76f0f9af3db8cb7299d0f8cf9df7876cbb3e0a (diff) |
Windows: fix object destruction order when terminating helper threads
Windows implementation of QLowEnergyController is using helper threads
to perform device connection and characteristics read for services.
In both cases a new QObject-derived class instance is created and moved
to a helper QThread. A QThread::finished signal was used to destroy both
the helper thread and the object. This was creating a situation when the
order of destruction for a thread and a nested object was not specified.
In practice that could lead to hangs when reading multiple service
characteristics, which is specially seen on Windows 11.
This patch uses QThread::finished signal to destroy only the nested
object. Later on, the object's QObject::destroyed signal is used to
destroy the thread itself.
Task-number: QTBUG-97578
Change-Id: Ic973b835496b6098d47cd1e124315903c143e3e1
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
(cherry picked from commit 981e3f10f48580641f5e2365953ec8a17b5c96a2)
-rw-r--r-- | src/bluetooth/qlowenergycontroller_winrt.cpp | 2 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_winrt_new.cpp | 4 |
2 files changed, 3 insertions, 3 deletions
diff --git a/src/bluetooth/qlowenergycontroller_winrt.cpp b/src/bluetooth/qlowenergycontroller_winrt.cpp index 9109102e..6d8898e9 100644 --- a/src/bluetooth/qlowenergycontroller_winrt.cpp +++ b/src/bluetooth/qlowenergycontroller_winrt.cpp @@ -642,8 +642,8 @@ void QLowEnergyControllerPrivateWinRT::discoverServiceDetails(const QBluetoothUu QThread *thread = new QThread; worker->moveToThread(thread); connect(thread, &QThread::started, worker, &QWinRTLowEnergyServiceHandler::obtainCharList); - connect(thread, &QThread::finished, thread, &QObject::deleteLater); connect(thread, &QThread::finished, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, thread, &QObject::deleteLater); connect(worker, &QWinRTLowEnergyServiceHandler::charListObtained, this, [this](const QBluetoothUuid &service, QHash<QLowEnergyHandle, QLowEnergyServicePrivate::CharData> charList , QVector<QBluetoothUuid> indicateChars diff --git a/src/bluetooth/qlowenergycontroller_winrt_new.cpp b/src/bluetooth/qlowenergycontroller_winrt_new.cpp index 5f8d5de5..e90073a4 100644 --- a/src/bluetooth/qlowenergycontroller_winrt_new.cpp +++ b/src/bluetooth/qlowenergycontroller_winrt_new.cpp @@ -711,8 +711,8 @@ void QLowEnergyControllerPrivateWinRTNew::connectToDevice() connect(this, &QLowEnergyControllerPrivateWinRTNew::abortConnection, worker, &QWinRTLowEnergyConnectionHandler::handleDeviceDisconnectRequest); connect(thread, &QThread::started, worker, &QWinRTLowEnergyConnectionHandler::connectToDevice); - connect(thread, &QThread::finished, thread, &QObject::deleteLater); connect(thread, &QThread::finished, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, thread, &QObject::deleteLater); connect(worker, &QWinRTLowEnergyConnectionHandler::errorOccurred, this, [this](const QString &msg) { handleConnectionError(msg.toUtf8().constData()); }); connect(worker, &QWinRTLowEnergyConnectionHandler::deviceConnected, this, @@ -1166,8 +1166,8 @@ void QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails(const QBluetoot QThread *thread = new QThread; worker->moveToThread(thread); connect(thread, &QThread::started, worker, &QWinRTLowEnergyServiceHandlerNew::obtainCharList); - connect(thread, &QThread::finished, thread, &QObject::deleteLater); connect(thread, &QThread::finished, worker, &QObject::deleteLater); + connect(worker, &QObject::destroyed, thread, &QObject::deleteLater); connect(worker, &QWinRTLowEnergyServiceHandlerNew::errorOccured, this, &QLowEnergyControllerPrivateWinRTNew::handleServiceHandlerError); connect(worker, &QWinRTLowEnergyServiceHandlerNew::charListObtained, this, |