summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJuha Vuolle <juha.vuolle@insta.fi>2022-06-20 09:13:58 +0300
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-06-21 07:17:14 +0000
commitd1048641beeee331f12a1bed5b6ce4c11a091031 (patch)
tree67af00680763840fd71a5075b1a7922065983092 /src
parent99bc4aadddf2a9d25fa98fa0bbcdd1db99a745f0 (diff)
Fix Bluez LE advertiser delete crash
Bluez LE advertiser and Bluez LE controller use/share an instance of HCI manager, and in some circumstances the deletion of the LE controller leads to a crash. This is because: 1) LE advertiser and HCI manager are parented to the LE controller 2) LE advertiser uses HCI manager in its destructor => When LE controller is deleted, its QObject children are deleted. If the HCI manager happens to be deleted first, the advertiser uses a by-now deleted HCI manager in its destructor This commit makes the HCI manager a shared resource so that the exact destruction order does not matter. As a drive-by set deleted cmacCalculator pointer to nullptr. Fixes: QTBUG-104105 Change-Id: I1c5e319af2fc59c4d5bb1fed33b8824eb3c4cb29 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> (cherry picked from commit f1ff9f4d17b82b5e597e28118de62beab705519e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/bluetooth/bluez/hcimanager.cpp4
-rw-r--r--src/bluetooth/bluez/hcimanager_p.h2
-rw-r--r--src/bluetooth/qleadvertiser_bluez.cpp11
-rw-r--r--src/bluetooth/qleadvertiser_bluez_p.h5
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez.cpp15
-rw-r--r--src/bluetooth/qlowenergycontroller_bluez_p.h2
6 files changed, 22 insertions, 17 deletions
diff --git a/src/bluetooth/bluez/hcimanager.cpp b/src/bluetooth/bluez/hcimanager.cpp
index 82dcc831..65cbd80e 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -21,8 +21,8 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_BLUEZ)
-HciManager::HciManager(const QBluetoothAddress& deviceAdapter, QObject *parent) :
- QObject(parent), hciSocket(-1), hciDev(-1)
+HciManager::HciManager(const QBluetoothAddress& deviceAdapter) :
+ QObject(nullptr), hciSocket(-1), hciDev(-1)
{
hciSocket = ::socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
if (hciSocket < 0) {
diff --git a/src/bluetooth/bluez/hcimanager_p.h b/src/bluetooth/bluez/hcimanager_p.h
index 4fb107e7..161675f3 100644
--- a/src/bluetooth/bluez/hcimanager_p.h
+++ b/src/bluetooth/bluez/hcimanager_p.h
@@ -156,7 +156,7 @@ public:
};
Q_ENUM(HciError);
- explicit HciManager(const QBluetoothAddress &deviceAdapter, QObject *parent = nullptr);
+ explicit HciManager(const QBluetoothAddress &deviceAdapter);
~HciManager();
bool isValid() const;
diff --git a/src/bluetooth/qleadvertiser_bluez.cpp b/src/bluetooth/qleadvertiser_bluez.cpp
index e4a1beea..ebf75b9f 100644
--- a/src/bluetooth/qleadvertiser_bluez.cpp
+++ b/src/bluetooth/qleadvertiser_bluez.cpp
@@ -49,23 +49,24 @@ static QByteArray byteArrayFromStruct(const T &data)
QLeAdvertiserBluez::QLeAdvertiserBluez(const QLowEnergyAdvertisingParameters &params,
const QLowEnergyAdvertisingData &advertisingData,
const QLowEnergyAdvertisingData &scanResponseData,
- HciManager &hciManager, QObject *parent)
+ std::shared_ptr<HciManager> hciManager, QObject *parent)
: QLeAdvertiser(params, advertisingData, scanResponseData, parent), m_hciManager(hciManager)
{
- connect(&m_hciManager, &HciManager::commandCompleted, this,
+ Q_ASSERT(m_hciManager);
+ connect(m_hciManager.get(), &HciManager::commandCompleted, this,
&QLeAdvertiserBluez::handleCommandCompleted);
}
QLeAdvertiserBluez::~QLeAdvertiserBluez()
{
- disconnect(&m_hciManager, &HciManager::commandCompleted, this,
+ disconnect(m_hciManager.get(), &HciManager::commandCompleted, this,
&QLeAdvertiserBluez::handleCommandCompleted);
doStopAdvertising();
}
void QLeAdvertiserBluez::doStartAdvertising()
{
- if (!m_hciManager.monitorEvent(HciManager::HciEvent::EVT_CMD_COMPLETE)) {
+ if (!m_hciManager->monitorEvent(HciManager::HciEvent::EVT_CMD_COMPLETE)) {
handleError();
return;
}
@@ -97,7 +98,7 @@ void QLeAdvertiserBluez::sendNextCommand()
return;
}
const Command &c = m_pendingCommands.first();
- if (!m_hciManager.sendCommand(QBluezConst::OgfLinkControl, c.ocf, c.data)) {
+ if (!m_hciManager->sendCommand(QBluezConst::OgfLinkControl, c.ocf, c.data)) {
handleError();
return;
}
diff --git a/src/bluetooth/qleadvertiser_bluez_p.h b/src/bluetooth/qleadvertiser_bluez_p.h
index b7227578..5bb5d968 100644
--- a/src/bluetooth/qleadvertiser_bluez_p.h
+++ b/src/bluetooth/qleadvertiser_bluez_p.h
@@ -68,7 +68,8 @@ class QLeAdvertiserBluez : public QLeAdvertiser
public:
QLeAdvertiserBluez(const QLowEnergyAdvertisingParameters &params,
const QLowEnergyAdvertisingData &advertisingData,
- const QLowEnergyAdvertisingData &scanResponseData, HciManager &hciManager,
+ const QLowEnergyAdvertisingData &scanResponseData,
+ std::shared_ptr<HciManager> hciManager,
QObject *parent = nullptr);
~QLeAdvertiserBluez() override;
@@ -97,7 +98,7 @@ private:
void handleCommandCompleted(quint16 opCode, quint8 status, const QByteArray &advertisingData);
void handleError();
- HciManager &m_hciManager;
+ std::shared_ptr<HciManager> m_hciManager;
struct Command {
Command() {}
diff --git a/src/bluetooth/qlowenergycontroller_bluez.cpp b/src/bluetooth/qlowenergycontroller_bluez.cpp
index af27d43e..bc790262 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -187,28 +187,30 @@ QLowEnergyControllerPrivateBluez::QLowEnergyControllerPrivateBluez()
void QLowEnergyControllerPrivateBluez::init()
{
- hciManager = new HciManager(localAdapter, this);
+ // The HCI manager is shared between this class and the advertiser
+ hciManager = std::make_shared<HciManager>(localAdapter);
+
if (!hciManager->isValid()){
setError(QLowEnergyController::InvalidBluetoothAdapterError);
return;
}
hciManager->monitorEvent(HciManager::HciEvent::EVT_ENCRYPT_CHANGE);
- connect(hciManager, SIGNAL(encryptionChangedEvent(QBluetoothAddress,bool)),
+ connect(hciManager.get(), SIGNAL(encryptionChangedEvent(QBluetoothAddress,bool)),
this, SLOT(encryptionChangedEvent(QBluetoothAddress,bool)));
hciManager->monitorEvent(HciManager::HciEvent::EVT_LE_META_EVENT);
hciManager->monitorAclPackets();
- connect(hciManager, &HciManager::connectionComplete, [this](quint16 handle) {
+ connect(hciManager.get(), &HciManager::connectionComplete, [this](quint16 handle) {
connectionHandle = handle;
qCDebug(QT_BT_BLUEZ) << "received connection complete event, handle:" << handle;
});
- connect(hciManager, &HciManager::connectionUpdate,
+ connect(hciManager.get(), &HciManager::connectionUpdate,
[this](quint16 handle, const QLowEnergyConnectionParameters &params) {
if (handle == connectionHandle)
emit q_ptr->connectionUpdated(params);
}
);
- connect(hciManager, &HciManager::signatureResolvingKeyReceived,
+ connect(hciManager.get(), &HciManager::signatureResolvingKeyReceived,
[this](quint16 handle, bool remoteKey, const quint128 &csrk) {
if (handle != connectionHandle)
return;
@@ -331,6 +333,7 @@ QLowEnergyControllerPrivateBluez::~QLowEnergyControllerPrivateBluez()
{
closeServerSocket();
delete cmacCalculator;
+ cmacCalculator = nullptr;
}
class ServerSocket
@@ -389,7 +392,7 @@ void QLowEnergyControllerPrivateBluez::startAdvertising(const QLowEnergyAdvertis
{
qCDebug(QT_BT_BLUEZ) << "Starting to advertise";
if (!advertiser) {
- advertiser = new QLeAdvertiserBluez(params, advertisingData, scanResponseData, *hciManager,
+ advertiser = new QLeAdvertiserBluez(params, advertisingData, scanResponseData, hciManager,
this);
connect(advertiser, &QLeAdvertiser::errorOccurred, this,
&QLowEnergyControllerPrivateBluez::handleAdvertisingError);
diff --git a/src/bluetooth/qlowenergycontroller_bluez_p.h b/src/bluetooth/qlowenergycontroller_bluez_p.h
index 15c99eef..320349c6 100644
--- a/src/bluetooth/qlowenergycontroller_bluez_p.h
+++ b/src/bluetooth/qlowenergycontroller_bluez_p.h
@@ -166,7 +166,7 @@ private:
bool encryptionChangePending;
bool receivedMtuExchangeRequest = false;
- HciManager *hciManager = nullptr;
+ std::shared_ptr<HciManager> hciManager;
QLeAdvertiser *advertiser = nullptr;
QSocketNotifier *serverSocketNotifier = nullptr;
QTimer *requestTimer = nullptr;