diff options
author | Juha Vuolle <juha.vuolle@insta.fi> | 2022-04-05 16:42:26 +0300 |
---|---|---|
committer | Juha Vuolle <juha.vuolle@insta.fi> | 2022-05-07 07:51:23 +0300 |
commit | 246ed1d9289c0ea576643c12fcde1ebdfb941500 (patch) | |
tree | 5e444f978174c6dd46efb03bdd588bcc669d0321 /src | |
parent | b865d41be6181b309808f432ee825dc84a670e62 (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.cpp | 31 |
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); |