summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2017-10-13 09:59:38 +0200
committerAlex Blasche <alexander.blasche@qt.io>2017-10-17 05:55:43 +0000
commit7a4cae77ccfca1ade80a76be7585b42b3d31c2d1 (patch)
treed020acd77abae38863003674befc97d7f7b53cc6 /src
parent80d85141aa496583c5cfa6dd0f62d5eb4a8ba660 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/bluez/remotedevicemanager.cpp5
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp15
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()