summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@insta.fi>2022-04-05 16:42:26 +0300
committerJuha Vuolle <juha.vuolle@insta.fi>2022-05-07 07:51:23 +0300
commit246ed1d9289c0ea576643c12fcde1ebdfb941500 (patch)
tree5e444f978174c6dd46efb03bdd588bcc669d0321 /src
parentb865d41be6181b309808f432ee825dc84a670e62 (diff)
Fix crash when service discovery agent (SDA) is stopped on Android
The SDA emits serviceDiscovered() signals for found services while processing them. The application code receiving the signal may call stop() on the SDA when it has received a service-of-interest, which in turn can lead to use of already released resources once the service processing resumes. While the signal is emitted in the populateDiscoveredServices(), the immediate crash was in _q_fetchUuidsTimeout() which calls it. That function unregisters the broadcast receiver, which was already released in stop(). This commit fixes this by making the serviceDiscovered() emission queued so that the service discovery reporting can finish before allowing further SDA calls. Pick-to: 5.15 6.2 6.3 Fixes: QTBUG-102319 Change-Id: I0059c1eaf3756e49b06b12da9e9f332602aa956e Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/qbluetoothservicediscoveryagent_android.cpp31
1 files changed, 20 insertions, 11 deletions
diff --git a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
index 61f306a8..48b09eff 100644
--- a/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
+++ b/src/bluetooth/qbluetoothservicediscoveryagent_android.cpp
@@ -259,9 +259,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::stop()
discoveredDevices.clear();
//kill receiver to limit load of signals
- receiver->unregisterReceiver();
- receiver->deleteLater();
- receiver = nullptr;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ receiver->deleteLater();
+ receiver = nullptr;
+ }
Q_Q(QBluetoothServiceDiscoveryAgent);
emit q->canceled();
@@ -474,8 +476,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::populateDiscoveredServices(const QB
//don't include the service if we already discovered it before
if (!isDuplicatedService(serviceInfo)) {
discoveredServices << serviceInfo;
- //qCDebug(QT_BT_ANDROID) << serviceInfo;
- emit q->serviceDiscovered(serviceInfo);
+ // Use queued connection to allow us finish the service discovery reporting;
+ // the application might call stop() when it has detected the service-of-interest,
+ // which in turn can cause the use of already released resources
+ QMetaObject::invokeMethod(q, "serviceDiscovered", Qt::QueuedConnection,
+ Q_ARG(QBluetoothServiceInfo, serviceInfo));
}
}
}
@@ -495,9 +500,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_fetchUuidsTimeout()
Q_ASSERT(sdpCache.isEmpty());
//kill receiver to limit load of signals
- receiver->unregisterReceiver();
- receiver->deleteLater();
- receiver = nullptr;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ receiver->deleteLater();
+ receiver = nullptr;
+ }
_q_serviceDiscoveryFinished();
}
@@ -512,9 +519,11 @@ void QBluetoothServiceDiscoveryAgentPrivate::_q_hostModeStateChanged(QBluetoothL
errorString = QBluetoothServiceDiscoveryAgent::tr("Device is powered off");
//kill receiver to limit load of signals
- receiver->unregisterReceiver();
- receiver->deleteLater();
- receiver = nullptr;
+ if (receiver) {
+ receiver->unregisterReceiver();
+ receiver->deleteLater();
+ receiver = nullptr;
+ }
Q_Q(QBluetoothServiceDiscoveryAgent);
emit q->errorOccurred(error);