[Linux] Do not reuse cancellable object (#31828)
* [Linux] Do not reuse cancellable object
Per documentation for g_cancellable_reset():
> Note that it is generally not a good idea to reuse an existing
> cancellable for more operations after it has been cancelled once, as
> this function might tempt you to do. The recommended practice is to
> drop the reference to a cancellable after cancelling it, and let it
> die with the outstanding async operations.
* Update cancellable in ChipDeviceScanner
diff --git a/src/platform/GLibTypeDeleter.h b/src/platform/GLibTypeDeleter.h
index 93ff40f..e6d9bfd 100644
--- a/src/platform/GLibTypeDeleter.h
+++ b/src/platform/GLibTypeDeleter.h
@@ -109,6 +109,12 @@
};
template <>
+struct GAutoPtrDeleter<GCancellable>
+{
+ using deleter = GObjectDeleter;
+};
+
+template <>
struct GAutoPtrDeleter<GDBusConnection>
{
using deleter = GObjectDeleter;
diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp
index 241c13e..12232bc 100644
--- a/src/platform/Linux/BLEManagerImpl.cpp
+++ b/src/platform/Linux/BLEManagerImpl.cpp
@@ -571,7 +571,7 @@
// Initializes the Bluez BLE layer if needed.
if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && !mFlags.Has(Flags::kBluezBLELayerInitialized))
{
- SuccessOrExit(err = mEndpoint.Init(mAdapterId, mIsCentral, nullptr));
+ SuccessOrExit(err = mEndpoint.Init(mIsCentral, mAdapterId));
mFlags.Set(Flags::kBluezBLELayerInitialized);
}
diff --git a/src/platform/Linux/bluez/BluezEndpoint.cpp b/src/platform/Linux/bluez/BluezEndpoint.cpp
index 24614eb..51a418b 100644
--- a/src/platform/Linux/bluez/BluezEndpoint.cpp
+++ b/src/platform/Linux/bluez/BluezEndpoint.cpp
@@ -656,22 +656,14 @@
return err;
}
-CHIP_ERROR BluezEndpoint::Init(uint32_t aAdapterId, bool aIsCentral, const char * apBleAddr)
+CHIP_ERROR BluezEndpoint::Init(bool aIsCentral, uint32_t aAdapterId)
{
- CHIP_ERROR err;
+ VerifyOrReturnError(!mIsInitialized, CHIP_ERROR_INCORRECT_STATE);
mAdapterId = aAdapterId;
mIsCentral = aIsCentral;
- if (apBleAddr != nullptr)
- mpAdapterAddr = g_strdup(apBleAddr);
-
- if (aIsCentral)
- {
- mpConnectCancellable = g_cancellable_new();
- }
-
- err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+ CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(
+[](BluezEndpoint * self) { return self->StartupEndpointBindings(); }, this);
VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "Failed to schedule endpoint initialization"));
@@ -681,6 +673,13 @@
return CHIP_NO_ERROR;
}
+CHIP_ERROR BluezEndpoint::Init(bool aIsCentral, const char * apBleAddr)
+{
+ VerifyOrReturnError(!mIsInitialized, CHIP_ERROR_INCORRECT_STATE);
+ mpAdapterAddr = g_strdup(apBleAddr);
+ return Init(aIsCentral, mAdapterId);
+}
+
void BluezEndpoint::Shutdown()
{
VerifyOrReturn(mIsInitialized);
@@ -707,8 +706,6 @@
g_object_unref(self->mpC2);
if (self->mpC3 != nullptr)
g_object_unref(self->mpC3);
- if (self->mpConnectCancellable != nullptr)
- g_object_unref(self->mpConnectCancellable);
return CHIP_NO_ERROR;
},
this);
@@ -744,7 +741,7 @@
g_clear_error(&MakeUniquePointerReceiver(error).Get());
bluez_device1_call_disconnect_sync(device, nullptr, &MakeUniquePointerReceiver(error).Get());
- bluez_device1_call_connect(device, params->mEndpoint.mpConnectCancellable, ConnectDeviceDone, params);
+ bluez_device1_call_connect(device, params->mEndpoint.mConnectCancellable.get(), ConnectDeviceDone, params);
return;
}
@@ -760,8 +757,7 @@
CHIP_ERROR BluezEndpoint::ConnectDeviceImpl(ConnectParams * apParams)
{
- g_cancellable_reset(apParams->mEndpoint.mpConnectCancellable);
- bluez_device1_call_connect(apParams->mpDevice, apParams->mEndpoint.mpConnectCancellable, ConnectDeviceDone, apParams);
+ bluez_device1_call_connect(apParams->mpDevice, apParams->mEndpoint.mConnectCancellable.get(), ConnectDeviceDone, apParams);
return CHIP_NO_ERROR;
}
@@ -770,6 +766,7 @@
auto params = chip::Platform::New<ConnectParams>(*this, &aDevice);
VerifyOrReturnError(params != nullptr, CHIP_ERROR_NO_MEMORY);
+ mConnectCancellable.reset(g_cancellable_new());
if (PlatformMgrImpl().GLibMatterContextInvokeSync(ConnectDeviceImpl, params) != CHIP_NO_ERROR)
{
ChipLogError(Ble, "Failed to schedule ConnectDeviceImpl() on CHIPoBluez thread");
@@ -782,8 +779,8 @@
void BluezEndpoint::CancelConnect()
{
- VerifyOrDie(mpConnectCancellable != nullptr);
- g_cancellable_cancel(mpConnectCancellable);
+ g_cancellable_cancel(mConnectCancellable.get());
+ mConnectCancellable.reset();
}
} // namespace Internal
diff --git a/src/platform/Linux/bluez/BluezEndpoint.h b/src/platform/Linux/bluez/BluezEndpoint.h
index 397b5a1..772b503 100644
--- a/src/platform/Linux/bluez/BluezEndpoint.h
+++ b/src/platform/Linux/bluez/BluezEndpoint.h
@@ -54,6 +54,7 @@
#include <ble/CHIPBleServiceData.h>
#include <lib/core/CHIPError.h>
+#include <platform/GLibTypeDeleter.h>
#include <platform/Linux/dbus/bluez/DbusBluez.h>
#include "BluezConnection.h"
@@ -69,7 +70,8 @@
BluezEndpoint() = default;
~BluezEndpoint() = default;
- CHIP_ERROR Init(uint32_t aAdapterId, bool aIsCentral, const char * apBleAddr);
+ CHIP_ERROR Init(bool aIsCentral, uint32_t aAdapterId);
+ CHIP_ERROR Init(bool aIsCentral, const char * apBleAddr);
void Shutdown();
BluezAdapter1 * GetAdapter() const { return mpAdapter; }
@@ -148,8 +150,8 @@
BluezGattCharacteristic1 * mpC3 = nullptr;
std::unordered_map<std::string, BluezConnection *> mConnMap;
- GCancellable * mpConnectCancellable = nullptr;
- char * mpPeerDevicePath = nullptr;
+ GAutoPtr<GCancellable> mConnectCancellable;
+ char * mpPeerDevicePath = nullptr;
// Allow BluezConnection to access our private members
friend class BluezConnection;
diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.cpp b/src/platform/Linux/bluez/ChipDeviceScanner.cpp
index 3a3115a..5d9cbf2 100644
--- a/src/platform/Linux/bluez/ChipDeviceScanner.cpp
+++ b/src/platform/Linux/bluez/ChipDeviceScanner.cpp
@@ -58,9 +58,8 @@
// Make this function idempotent by shutting down previously initialized state if any.
Shutdown();
- mAdapter = BLUEZ_ADAPTER1(g_object_ref(adapter));
- mCancellable = g_cancellable_new();
- mDelegate = delegate;
+ mAdapter = BLUEZ_ADAPTER1(g_object_ref(adapter));
+ mDelegate = delegate;
// Create the D-Bus object manager client object on the glib thread, so that all D-Bus signals
// will be delivered to the glib thread.
@@ -73,7 +72,7 @@
self->mManager = g_dbus_object_manager_client_new_for_bus_sync(
G_BUS_TYPE_SYSTEM, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, BLUEZ_INTERFACE, "/",
bluez_object_manager_client_get_proxy_type, nullptr /* unused user data in the Proxy Type Func */,
- nullptr /* destroy notify */, self->mCancellable, &MakeUniquePointerReceiver(err).Get());
+ nullptr /* destroy notify */, nullptr /* cancellable */, &MakeUniquePointerReceiver(err).Get());
VerifyOrReturnError(self->mManager != nullptr, CHIP_ERROR_INTERNAL,
ChipLogError(Ble, "Failed to get D-Bus object manager for device scanning: %s", err->message));
return CHIP_NO_ERROR;
@@ -100,8 +99,6 @@
g_object_unref(self->mManager);
if (self->mAdapter != nullptr)
g_object_unref(self->mAdapter);
- if (self->mCancellable != nullptr)
- g_object_unref(self->mCancellable);
return CHIP_NO_ERROR;
},
this);
@@ -115,6 +112,7 @@
VerifyOrReturnError(mScannerState != ChipDeviceScannerState::SCANNER_SCANNING, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mTimerState == ScannerTimerState::TIMER_CANCELED, CHIP_ERROR_INCORRECT_STATE);
+ mCancellable.reset(g_cancellable_new());
if (PlatformMgrImpl().GLibMatterContextInvokeSync(MainLoopStartScan, this) != CHIP_NO_ERROR)
{
ChipLogError(Ble, "Failed to schedule BLE scan start.");
@@ -191,7 +189,9 @@
{
GAutoPtr<GError> error;
- g_cancellable_cancel(self->mCancellable); // in case we are currently running a scan
+ // In case we are currently running a scan
+ g_cancellable_cancel(self->mCancellable.get());
+ self->mCancellable.reset();
if (self->mObjectAddedSignal)
{
@@ -303,7 +303,7 @@
g_variant_builder_add(&filterBuilder, "{sv}", "Transport", g_variant_new_string("le"));
GVariant * filter = g_variant_builder_end(&filterBuilder);
- if (!bluez_adapter1_call_set_discovery_filter_sync(self->mAdapter, filter, self->mCancellable,
+ if (!bluez_adapter1_call_set_discovery_filter_sync(self->mAdapter, filter, self->mCancellable.get(),
&MakeUniquePointerReceiver(error).Get()))
{
// Not critical: ignore if fails
@@ -312,7 +312,8 @@
}
ChipLogProgress(Ble, "BLE initiating scan.");
- if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter, self->mCancellable, &MakeUniquePointerReceiver(error).Get()))
+ if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter, self->mCancellable.get(),
+ &MakeUniquePointerReceiver(error).Get()))
{
ChipLogError(Ble, "Failed to start discovery: %s", error->message);
return CHIP_ERROR_INTERNAL;
diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.h b/src/platform/Linux/bluez/ChipDeviceScanner.h
index 4785a73..1271ec3 100644
--- a/src/platform/Linux/bluez/ChipDeviceScanner.h
+++ b/src/platform/Linux/bluez/ChipDeviceScanner.h
@@ -23,6 +23,7 @@
#include <ble/CHIPBleServiceData.h>
#include <lib/core/CHIPError.h>
+#include <platform/GLibTypeDeleter.h>
#include <platform/Linux/dbus/bluez/DbusBluez.h>
#include <system/SystemLayer.h>
@@ -106,13 +107,13 @@
GDBusObjectManager * mManager = nullptr;
BluezAdapter1 * mAdapter = nullptr;
- GCancellable * mCancellable = nullptr;
ChipDeviceScannerDelegate * mDelegate = nullptr;
gulong mObjectAddedSignal = 0;
gulong mInterfaceChangedSignal = 0;
ChipDeviceScannerState mScannerState = ChipDeviceScannerState::SCANNER_UNINITIALIZED;
/// Used to track if timer has already expired and doesn't need to be canceled.
ScannerTimerState mTimerState = ScannerTimerState::TIMER_CANCELED;
+ GAutoPtr<GCancellable> mCancellable;
};
} // namespace Internal