diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2018-06-22 13:41:47 +0200 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2018-06-26 19:15:29 +0000 |
commit | 9b7a4c10b67dd7d89ed30f1f94d8982dab47ded0 (patch) | |
tree | 45f3e1b63cf29c6c9474c39e21ddb1a220b65b29 /src | |
parent | c754e16ceddaf6826d2a74775df8409b3278d5b8 (diff) |
Fix crash in QLEController caused by random device disconnect
This only happens with Bluez 5.42 or later versions as the DBus based GATT
central client is used. The peripheral disconnects in the middle of a char
or descriptor write request. The disconnect triggers the cleanup of all
internal states. The write char/descriptor dbus request returns after the
disconnect and executes in the context of an already reset
QLowEnergyController instance.
The fix ensures that the call back code does not make the assumption
of operating with a connected peripheral. In fact the code had the
relevant asserts already.
[ChangeLog][QtBluetooth][PLatform Specific Changes] Fixed crash in
DBus gatt central backend (BlueZ5) caused by device disconnecting
and pending dbus call watcher returning later after disconnect.
Task-number: QTBUG-68890
Change-Id: Iad9b8a1cfc8d916d49fd9b71b2d8f03b9c90639b
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth/qlowenergycontroller_bluezdbus.cpp | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp index 8f001f92..16f03405 100644 --- a/src/bluetooth/qlowenergycontroller_bluezdbus.cpp +++ b/src/bluetooth/qlowenergycontroller_bluezdbus.cpp @@ -560,8 +560,12 @@ void QLowEnergyControllerPrivateBluezDBus::prepareNextJob() void QLowEnergyControllerPrivateBluezDBus::onCharReadFinished(QDBusPendingCallWatcher *call) { - Q_ASSERT(jobPending); - Q_ASSERT(!jobs.isEmpty()); + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onCharReadFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } const GattJob nextJob = jobs.constFirst(); Q_ASSERT(nextJob.flags.testFlag(GattJob::CharRead)); @@ -604,8 +608,12 @@ void QLowEnergyControllerPrivateBluezDBus::onCharReadFinished(QDBusPendingCallWa void QLowEnergyControllerPrivateBluezDBus::onDescReadFinished(QDBusPendingCallWatcher *call) { - Q_ASSERT(jobPending); - Q_ASSERT(!jobs.isEmpty()); + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onDescReadFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } const GattJob nextJob = jobs.constFirst(); Q_ASSERT(nextJob.flags.testFlag(GattJob::DescRead)); @@ -666,8 +674,12 @@ void QLowEnergyControllerPrivateBluezDBus::onDescReadFinished(QDBusPendingCallWa void QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished(QDBusPendingCallWatcher *call) { - Q_ASSERT(jobPending); - Q_ASSERT(!jobs.isEmpty()); + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onCharWriteFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } const GattJob nextJob = jobs.constFirst(); Q_ASSERT(nextJob.flags.testFlag(GattJob::CharWrite)); @@ -707,8 +719,12 @@ void QLowEnergyControllerPrivateBluezDBus::onCharWriteFinished(QDBusPendingCallW void QLowEnergyControllerPrivateBluezDBus::onDescWriteFinished(QDBusPendingCallWatcher *call) { - Q_ASSERT(jobPending); - Q_ASSERT(!jobs.isEmpty()); + if (!jobPending || jobs.isEmpty()) { + // this may happen when service disconnects before dbus watcher returns later on + qCWarning(QT_BT_BLUEZ) << "Aborting onDescWriteFinished due to disconnect"; + Q_ASSERT(state == QLowEnergyController::UnconnectedState); + return; + } const GattJob nextJob = jobs.constFirst(); Q_ASSERT(nextJob.flags.testFlag(GattJob::DescWrite)); |