summaryrefslogtreecommitdiffstats
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-22 06:09:31 +0000
commitba7f545a8920be04a800694f1138e33080dd8c8c (patch)
tree888f349e88745d36e3e6dec2f08d3517824c98ee
parent1d5d325b8c1b2c086f8a1e1bc66779e0af009ec1 (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>
-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 43faec22..8b6b52b4 100644
--- a/src/bluetooth/bluez/hcimanager.cpp
+++ b/src/bluetooth/bluez/hcimanager.cpp
@@ -57,8 +57,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 d624edc7..69bf7e48 100644
--- a/src/bluetooth/bluez/hcimanager_p.h
+++ b/src/bluetooth/bluez/hcimanager_p.h
@@ -192,7 +192,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 22d77ee8..e0ef450f 100644
--- a/src/bluetooth/qleadvertiser_bluez.cpp
+++ b/src/bluetooth/qleadvertiser_bluez.cpp
@@ -82,23 +82,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;
}
@@ -130,7 +131,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 683bd25f..312889d3 100644
--- a/src/bluetooth/qleadvertiser_bluez_p.h
+++ b/src/bluetooth/qleadvertiser_bluez_p.h
@@ -104,7 +104,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;
@@ -133,7 +134,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 406bdecd..4718f0a8 100644
--- a/src/bluetooth/qlowenergycontroller_bluez.cpp
+++ b/src/bluetooth/qlowenergycontroller_bluez.cpp
@@ -223,28 +223,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;
@@ -367,6 +369,7 @@ QLowEnergyControllerPrivateBluez::~QLowEnergyControllerPrivateBluez()
{
closeServerSocket();
delete cmacCalculator;
+ cmacCalculator = nullptr;
}
class ServerSocket
@@ -425,7 +428,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 6f373479..d622de7d 100644
--- a/src/bluetooth/qlowenergycontroller_bluez_p.h
+++ b/src/bluetooth/qlowenergycontroller_bluez_p.h
@@ -202,7 +202,7 @@ private:
bool encryptionChangePending;
bool receivedMtuExchangeRequest = false;
- HciManager *hciManager = nullptr;
+ std::shared_ptr<HciManager> hciManager;
QLeAdvertiser *advertiser = nullptr;
QSocketNotifier *serverSocketNotifier = nullptr;
QTimer *requestTimer = nullptr;