diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2017-10-13 09:59:38 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2017-10-17 05:55:43 +0000 |
commit | 7a4cae77ccfca1ade80a76be7585b42b3d31c2d1 (patch) | |
tree | d020acd77abae38863003674befc97d7f7b53cc6 | |
parent | 80d85141aa496583c5cfa6dd0f62d5eb4a8ba660 (diff) | |
download | qtconnectivity-7a4cae77ccfca1ade80a76be7585b42b3d31c2d1.tar.gz |
Fix crash due to inconsistent state in QLEController during JobDisconnectDevice
This bug was caused by a problem in the patch for QTBUG-55150.
While the termination of an ongoing BTLE connection is being
processed, the QLEController instance is in Connecting state and
the internal socket is still null. If the user triggers a call
to QLEController::disconnectDevice() while the above state is
pending, it crashes due to a call to the socket's close()
function. The time window for this to happen is very small.
It takes the duration of the bluez dbus call to disconnect
a device.
This patch addresses the above crash bug and adds a
bit more debug output to catch similar cases later on.
Task-number: QTBUG-63619
Change-Id: I893990a9ce8ccf55ddbf619fe177379f79dc9ee3
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r-- | src/bluetooth/bluez/remotedevicemanager.cpp | 5 | ||||
-rw-r--r-- | src/bluetooth/qlowenergycontroller_bluez.cpp | 15 |
2 files changed, 17 insertions, 3 deletions
diff --git a/src/bluetooth/bluez/remotedevicemanager.cpp b/src/bluetooth/bluez/remotedevicemanager.cpp index f63b21e6..5d17d571 100644 --- a/src/bluetooth/bluez/remotedevicemanager.cpp +++ b/src/bluetooth/bluez/remotedevicemanager.cpp @@ -106,6 +106,7 @@ void RemoteDeviceManager::prepareNextJob() jobQueue.pop_front(); jobInProgress = false; + qDebug(QT_BT_BLUEZ) << "RemoteDeviceManager job queue status:" << jobQueue.empty(); if (jobQueue.empty()) emit finished(); else @@ -163,8 +164,10 @@ void RemoteDeviceManager::disconnectDevice(const QBluetoothAddress &remote) } } - if (!jobStarted) + if (!jobStarted) { + qDebug(QT_BT_BLUEZ) << "RemoteDeviceManager JobDisconnectDevice failed"; QTimer::singleShot(0, this, [this](){ prepareNextJob(); }); + } } QT_END_NAMESPACE diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index 0744bcc4..d80389da 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -527,8 +527,10 @@ void QLowEnergyControllerPrivate::connectToDevice() } setState(QLowEnergyController::ConnectingState); - if (l2cpSocket) + if (l2cpSocket) { delete l2cpSocket; + l2cpSocket = nullptr; + } createServicesForCentralIfRequired(); @@ -581,6 +583,7 @@ void QLowEnergyControllerPrivate::activeConnectionTerminationDone() qCWarning(QT_BT_BLUEZ) << "Cannot close pending external BTLE connections. Aborting connect attempt"; setError(QLowEnergyController::ConnectionError); setState(QLowEnergyController::UnconnectedState); + l2cpDisconnected(); return; } else { establishL2cpClientSocket(); @@ -726,8 +729,16 @@ void QLowEnergyControllerPrivate::l2cpConnected() void QLowEnergyControllerPrivate::disconnectFromDevice() { setState(QLowEnergyController::ClosingState); - l2cpSocket->close(); + if (l2cpSocket) + l2cpSocket->close(); resetController(); + + // this may happen when RemoteDeviceManager::JobType::JobDisconnectDevice + // is pending. + if (!l2cpSocket) { + qWarning(QT_BT_BLUEZ) << "Unexpected closure of device. Cleaning up internal states."; + l2cpDisconnected(); + } } void QLowEnergyControllerPrivate::l2cpDisconnected() |