From 7262bf89d3a67eb624e850a30bd40b3f4e257bac Mon Sep 17 00:00:00 2001 From: Alex Blasche Date: Fri, 17 Nov 2017 13:43:01 +0100 Subject: BlueZ: Prevent hanging of QLEController job queue due to comm timeout When an ATT READ_REQUEST times out the ATT stack stops spinning the event queue. This is particularly bad during the initial service discovery when a lot of read requests are scheduled in one go. The consequence was that the QLEService instance was stuck in the ServiceDiscovering state. Subsequently the service object is unusable. The patch ensures that the ATT event loop continues after the timeout happens. If multiple char or descriptor reads (on the same service) have this problem the service discovery can still take a very long time. The user can adjust this via the BLUETOOTH_GATT_TIMEOUT env variable. [ChangeLog][Platform Specific Behavior][BlueZ] Fixed hanging service discovery state when remote device does not respond to ATT read requests. Task-number: QTBUG-64669 Change-Id: I8d22c13b825a921b140213b8b67e59e2310c362c Reviewed-by: Oliver Wolff Reviewed-by: Alex Blasche --- src/bluetooth/qlowenergycontroller_bluez.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp index d80389da..3359edf0 100644 --- a/src/bluetooth/qlowenergycontroller_bluez.cpp +++ b/src/bluetooth/qlowenergycontroller_bluez.cpp @@ -346,8 +346,8 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() } if (!openRequests.isEmpty() && requestPending) { - requestPending = false; // reset pending flag const Request currentRequest = openRequests.dequeue(); + requestPending = false; // reset pending flag qCWarning(QT_BT_BLUEZ).nospace() << "****** Request type 0x" << hex << currentRequest.command << " to server/peripheral timed out"; @@ -372,7 +372,6 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() case ATT_OP_EXCHANGE_MTU_REQUEST: // MTU change request // never received reply to MTU request // it is safe to skip and go to next request - sendNextPendingRequest(); break; case ATT_OP_READ_BY_GROUP_REQUEST: // primary or secondary service discovery case ATT_OP_READ_BY_TYPE_REQUEST: // characteristic or included service discovery @@ -406,8 +405,13 @@ void QLowEnergyControllerPrivate::handleGattRequestTimeout() break; default: // not a command used by central role implementation - return; + qCWarning(QT_BT_BLUEZ) << "Missing response for ATT peripheral command: " + << hex << command; + break; } + + // spin openRequest queue further + sendNextPendingRequest(); } } -- cgit v1.2.3