From e25d61b38a426ffd743d5d067bee5ea0951ca947 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Fri, 4 Nov 2022 15:09:34 +0100 Subject: [PATCH] [Linux] Run only one GLib main event loop (#23320) * Unregister from BlueZ when shutting down BLE manager * Return CHIP_ERROR from all BlueZ helper functions * Remove not used class method * Remove D-Bus connection handler from PlatformManager The D-Bus connection handler stored in the PlatformManager is not used anywhere. It's not required to pre-connect to D-Bus, because the connection (for given bus type) returned by the g_bus_get_sync() function is shared with other callers. * Run only one GLib main event loop per Matter SDK It is not necessary to start new GLib main event loop for every new D-Bus communication with external service. Single main event loop can handle all such communication. * Run WiFi IP address change listener in GLib main loop * Properly release cancellable object on cleanup * Explicitly wait for glib main thread to exit * Workaround for TSAN false positive reports with glib TSAN thinks that memory accessed before the call to g_source_attach() (which is internally used by e.g. g_main_context_invoke() and g_idle_add()) needs to be guarded by a mutex, otherwise that's a race condition between the thread that is creating shared data (the current thread) and the glib main event loop thread. In fact such race condition does not occur because g_source_attach() acts here as pthread_create() - code is not executed on the other thread before the g_source_attach() is called. Co-authored-by: Andrei Litvin --- src/controller/python/chip/ble/LinuxImpl.cpp | 3 +- src/platform/BUILD.gn | 2 - src/platform/Linux/BLEManagerImpl.cpp | 36 +++- src/platform/Linux/BUILD.gn | 2 - src/platform/Linux/CHIPDevicePlatformConfig.h | 8 + src/platform/Linux/PlatformManagerImpl.cpp | 185 ++++++++++++----- src/platform/Linux/PlatformManagerImpl.h | 65 ++++-- .../Linux/bluez/ChipDeviceScanner.cpp | 17 +- src/platform/Linux/bluez/Helper.cpp | 118 +++++------ src/platform/Linux/bluez/Helper.h | 12 +- src/platform/Linux/bluez/MainLoop.cpp | 187 ------------------ src/platform/Linux/bluez/MainLoop.h | 108 ---------- src/platform/android/PlatformManagerImpl.h | 2 +- src/platform/webos/CHIPDevicePlatformConfig.h | 8 + src/platform/webos/PlatformManagerImpl.cpp | 63 +++--- src/platform/webos/PlatformManagerImpl.h | 23 +-- 16 files changed, 329 insertions(+), 510 deletions(-) delete mode 100644 src/platform/Linux/bluez/MainLoop.cpp delete mode 100644 src/platform/Linux/bluez/MainLoop.h diff --git a/src/controller/python/chip/ble/LinuxImpl.cpp b/src/controller/python/chip/ble/LinuxImpl.cpp index 1094662eaae02d..c084f957d44d1c 100644 --- a/src/controller/python/chip/ble/LinuxImpl.cpp +++ b/src/controller/python/chip/ble/LinuxImpl.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include using namespace chip::DeviceLayer::Internal; @@ -58,7 +57,7 @@ extern "C" void * pychip_ble_adapter_list_get_raw_adapter(void * adapterIterator namespace { -// To avoid pythoon compatibility issues on inc/dec references, +// To avoid python compatibility issues on inc/dec references, // code assumes an abstract type and leaves it up to python to keep track of // reference counts struct PyObject; diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index 92d8adc36e4f21..f9b9e966948d68 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -91,7 +91,6 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { header = "CHIPDeviceBuildConfig.h" header_dir = "platform" - chip_with_gio = chip_enable_wifi chip_device_config_enable_wpa = chip_enable_wifi && chip_device_platform != "darwin" chip_stack_lock_tracking_log = chip_stack_lock_tracking != "none" @@ -100,7 +99,6 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { "CHIP_DEVICE_CONFIG_ENABLE_WPA=${chip_device_config_enable_wpa}", "CHIP_ENABLE_OPENTHREAD=${chip_enable_openthread}", "CHIP_DEVICE_CONFIG_THREAD_FTD=${chip_device_config_thread_ftd}", - "CHIP_WITH_GIO=${chip_with_gio}", "CHIP_STACK_LOCK_TRACKING_ENABLED=${chip_stack_lock_tracking_log}", "CHIP_STACK_LOCK_TRACKING_ERROR_FATAL=${chip_stack_lock_tracking_fatal}", "CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING=${chip_enable_additional_data_advertising}", diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 348c552f30818c..2c2a8794c66105 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -97,6 +97,9 @@ void BLEManagerImpl::_Shutdown() { // ensure scan resources are cleared (e.g. timeout timers) mDeviceScanner.reset(); + // Release BLE connection resources (unregister from BlueZ). + ShutdownBluezBleLayer(mpEndpoint); + mFlags.Clear(Flags::kBluezBLELayerInitialized); } CHIP_ERROR BLEManagerImpl::_SetAdvertisingEnabled(bool val) @@ -348,7 +351,10 @@ bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX), ChipLogError(DeviceLayer, "SubscribeCharacteristic() called with invalid characteristic ID")); - result = BluezSubscribeCharacteristic(conId); + VerifyOrExit(BluezSubscribeCharacteristic(conId) == CHIP_NO_ERROR, + ChipLogError(DeviceLayer, "BluezSubscribeCharacteristic() failed")); + result = true; + exit: return result; } @@ -362,21 +368,38 @@ bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, cons VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_TX), ChipLogError(DeviceLayer, "UnsubscribeCharacteristic() called with invalid characteristic ID")); - result = BluezUnsubscribeCharacteristic(conId); + VerifyOrExit(BluezUnsubscribeCharacteristic(conId) == CHIP_NO_ERROR, + ChipLogError(DeviceLayer, "BluezUnsubscribeCharacteristic() failed")); + result = true; + exit: return result; } bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId) { + bool result = false; + ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %p)", conId); - return CloseBluezConnection(conId); + + VerifyOrExit(CloseBluezConnection(conId) == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "CloseBluezConnection() failed")); + result = true; + +exit: + return result; } bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, chip::System::PacketBufferHandle pBuf) { - return SendBluezIndication(conId, std::move(pBuf)); + bool result = false; + + VerifyOrExit(SendBluezIndication(conId, std::move(pBuf)) == CHIP_NO_ERROR, + ChipLogError(DeviceLayer, "SendBluezIndication() failed")); + result = true; + +exit: + return result; } bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId, @@ -389,7 +412,10 @@ bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::Ch VerifyOrExit(Ble::UUIDsMatch(charId, &ChipUUID_CHIPoBLEChar_RX), ChipLogError(DeviceLayer, "SendWriteRequest() called with invalid characteristic ID")); - result = BluezSendWriteRequest(conId, std::move(pBuf)); + VerifyOrExit(BluezSendWriteRequest(conId, std::move(pBuf)) == CHIP_NO_ERROR, + ChipLogError(DeviceLayer, "BluezSendWriteRequest() failed")); + result = true; + exit: return result; } diff --git a/src/platform/Linux/BUILD.gn b/src/platform/Linux/BUILD.gn index b90ae87bbfab83..69d0289254d063 100644 --- a/src/platform/Linux/BUILD.gn +++ b/src/platform/Linux/BUILD.gn @@ -91,8 +91,6 @@ static_library("Linux") { "bluez/ChipDeviceScanner.h", "bluez/Helper.cpp", "bluez/Helper.h", - "bluez/MainLoop.cpp", - "bluez/MainLoop.h", "bluez/Types.h", ] } diff --git a/src/platform/Linux/CHIPDevicePlatformConfig.h b/src/platform/Linux/CHIPDevicePlatformConfig.h index 53b7b05b615d71..05cdd7b983b86f 100644 --- a/src/platform/Linux/CHIPDevicePlatformConfig.h +++ b/src/platform/Linux/CHIPDevicePlatformConfig.h @@ -41,6 +41,14 @@ #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0 #endif +// Start GLib main event loop if BLE or WiFi is enabled. This is needed to handle +// D-Bus communication with BlueZ or wpa_supplicant. +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE || CHIP_DEVICE_CONFIG_ENABLE_WIFI +#define CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 1 +#else +#define CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 0 +#endif + // ========== Platform-specific Configuration ========= // These are configuration options that are unique to Linux platforms. diff --git a/src/platform/Linux/PlatformManagerImpl.cpp b/src/platform/Linux/PlatformManagerImpl.cpp index d92203a0dfacd6..9daa120976dfd4 100644 --- a/src/platform/Linux/PlatformManagerImpl.cpp +++ b/src/platform/Linux/PlatformManagerImpl.cpp @@ -24,6 +24,17 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include #include #include @@ -35,22 +46,6 @@ #include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 -#include -#define gettid() syscall(SYS_gettid) -#endif - using namespace ::chip::app::Clusters; namespace chip { @@ -60,41 +55,32 @@ PlatformManagerImpl PlatformManagerImpl::sInstance; namespace { -#if CHIP_WITH_GIO -void GDBus_Thread() +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP +void * GLibMainLoopThread(void * loop) { - GMainLoop * loop = g_main_loop_new(nullptr, false); - - g_main_loop_run(loop); - g_main_loop_unref(loop); + g_main_loop_run(static_cast(loop)); + return nullptr; } #endif -} // namespace #if CHIP_DEVICE_CONFIG_ENABLE_WIFI -void PlatformManagerImpl::WiFIIPChangeListener() + +gboolean WiFiIPChangeListener(GIOChannel * ch, GIOCondition /* condition */, void * /* userData */) { - int sock; - if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) - { - ChipLogError(DeviceLayer, "Failed to init netlink socket for ip addresses."); - return; - } - struct sockaddr_nl addr; - memset(&addr, 0, sizeof(addr)); - addr.nl_family = AF_NETLINK; - addr.nl_groups = RTMGRP_IPV4_IFADDR; + char buffer[4096]; + auto * header = reinterpret_cast(buffer); + ssize_t len; - if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) + if ((len = recv(g_io_channel_unix_get_fd(ch), buffer, sizeof(buffer), 0)) == -1) { - ChipLogError(DeviceLayer, "Failed to bind netlink socket for ip addresses."); - return; + if (errno == EINTR || errno == EAGAIN) + return G_SOURCE_CONTINUE; + ChipLogError(DeviceLayer, "Error reading from netlink socket: %d", errno); + return G_SOURCE_CONTINUE; } - ssize_t len; - char buffer[4096]; - for (struct nlmsghdr * header = reinterpret_cast(buffer); (len = recv(sock, header, sizeof(buffer), 0)) > 0;) + if (len > 0) { for (struct nlmsghdr * messageHeader = header; (NLMSG_OK(messageHeader, static_cast(len))) && (messageHeader->nlmsg_type != NLMSG_DONE); @@ -154,23 +140,70 @@ void PlatformManagerImpl::WiFIIPChangeListener() } } } + else + { + ChipLogError(DeviceLayer, "EOF on netlink socket"); + return G_SOURCE_REMOVE; + } + + return G_SOURCE_CONTINUE; } + +// The temporary hack for getting IP address change on linux for network provisioning in the rendezvous session. +// This should be removed or find a better place once we deprecate the rendezvous session. +CHIP_ERROR RunWiFiIPChangeListener() +{ + int sock; + if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) + { + ChipLogError(DeviceLayer, "Failed to init netlink socket for IP addresses: %d", errno); + return CHIP_ERROR_INTERNAL; + } + + struct sockaddr_nl addr; + memset(&addr, 0, sizeof(addr)); + addr.nl_family = AF_NETLINK; + addr.nl_groups = RTMGRP_IPV4_IFADDR; + + if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1) + { + ChipLogError(DeviceLayer, "Failed to bind netlink socket for IP addresses: %d", errno); + close(sock); + return CHIP_ERROR_INTERNAL; + } + + GIOChannel * ch = g_io_channel_unix_new(sock); + g_io_add_watch_full(ch, G_PRIORITY_DEFAULT, G_IO_IN, WiFiIPChangeListener, nullptr, nullptr); + + g_io_channel_set_close_on_unref(ch, TRUE); + g_io_channel_set_encoding(ch, nullptr, nullptr); + g_io_channel_unref(ch); + + return CHIP_NO_ERROR; +} + #endif // #if CHIP_DEVICE_CONFIG_ENABLE_WIFI +} // namespace + CHIP_ERROR PlatformManagerImpl::_InitChipStack() { -#if CHIP_WITH_GIO - GError * error = nullptr; +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP - this->mpGDBusConnection = UniqueGDBusConnection(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error)); + mGLibMainLoop = g_main_loop_new(nullptr, FALSE); + mGLibMainLoopThread = g_thread_new("gmain-matter", GLibMainLoopThread, mGLibMainLoop); + + { + std::unique_lock lock(mGLibMainLoopCallbackIndirectionMutex); + CallbackIndirection startedInd([](void *) { return G_SOURCE_REMOVE; }, nullptr); + g_idle_add(G_SOURCE_FUNC(&CallbackIndirection::Callback), &startedInd); + startedInd.Wait(lock); + } - std::thread gdbusThread(GDBus_Thread); - gdbusThread.detach(); #endif #if CHIP_DEVICE_CONFIG_ENABLE_WIFI - std::thread wifiIPThread(WiFIIPChangeListener); - wifiIPThread.detach(); + ReturnErrorOnFailure(RunWiFiIPChangeListener()); #endif // Initialize the configuration system. @@ -212,14 +245,64 @@ void PlatformManagerImpl::_Shutdown() } Internal::GenericPlatformManagerImpl_POSIX::_Shutdown(); + +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP + g_main_loop_quit(mGLibMainLoop); + g_main_loop_unref(mGLibMainLoop); + g_thread_join(mGLibMainLoopThread); +#endif } -#if CHIP_WITH_GIO -GDBusConnection * PlatformManagerImpl::GetGDBusConnection() +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP + +void PlatformManagerImpl::CallbackIndirection::Wait(std::unique_lock & lock) { - return this->mpGDBusConnection.get(); + mDoneCond.wait(lock, [this]() { return mDone; }); } -#endif + +gboolean PlatformManagerImpl::CallbackIndirection::Callback(CallbackIndirection * self) +{ + // We can not access "self" before acquiring the lock, because TSAN will complain that + // there is a race condition between the thread that created the object and the thread + // that is executing the callback. + std::unique_lock lock(PlatformMgrImpl().mGLibMainLoopCallbackIndirectionMutex); + + auto callback = self->mCallback; + auto userData = self->mUserData; + + lock.unlock(); + auto result = callback(userData); + lock.lock(); + + self->mDone = true; + self->mDoneCond.notify_all(); + + return result; +} + +#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE +CHIP_ERROR PlatformManagerImpl::RunOnGLibMainLoopThread(GSourceFunc callback, void * userData, bool wait) +{ + + GMainContext * context = g_main_loop_get_context(mGLibMainLoop); + VerifyOrReturnError(context != nullptr, + (ChipLogDetail(DeviceLayer, "Failed to get GLib main loop context"), CHIP_ERROR_INTERNAL)); + + if (wait) + { + std::unique_lock lock(mGLibMainLoopCallbackIndirectionMutex); + CallbackIndirection indirection(callback, userData); + g_main_context_invoke(context, G_SOURCE_FUNC(&CallbackIndirection::Callback), &indirection); + indirection.Wait(lock); + return CHIP_NO_ERROR; + } + + g_main_context_invoke(context, callback, userData); + return CHIP_NO_ERROR; +} +#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + +#endif // CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/Linux/PlatformManagerImpl.h b/src/platform/Linux/PlatformManagerImpl.h index fb1f25cd248211..bc5bc7c10c4e4a 100644 --- a/src/platform/Linux/PlatformManagerImpl.h +++ b/src/platform/Linux/PlatformManagerImpl.h @@ -23,10 +23,13 @@ #pragma once +#include +#include + #include #include -#if CHIP_WITH_GIO +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP #include #endif @@ -50,8 +53,28 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener public: // ===== Platform-specific members that may be accessed directly by the application. -#if CHIP_WITH_GIO - GDBusConnection * GetGDBusConnection(); + +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP && CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE + + /** + * @brief Executes a callback in the GLib main loop thread. + * + * @param[in] callback The callback to execute. + * @param[in] userData User data to pass to the callback. + * @param[in] wait If true, the function will block until the callback has been executed. + * @returns CHIP_NO_ERROR if the callback was successfully executed. + */ + CHIP_ERROR RunOnGLibMainLoopThread(GSourceFunc callback, void * userData, bool wait = false); + + /** + * @brief Convenience method to require less casts to void pointers. + */ + template + CHIP_ERROR ScheduleOnGLibMainLoopThread(int (*callback)(T *), T * userData, bool wait = false) + { + return RunOnGLibMainLoopThread(G_SOURCE_FUNC(callback), userData, wait); + } + #endif System::Clock::Timestamp GetStartTime() { return mStartTime; } @@ -72,18 +95,36 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener static PlatformManagerImpl sInstance; - // The temporary hack for getting IP address change on linux for network provisioning in the rendezvous session. - // This should be removed or find a better place once we depercate the rendezvous session. - static void WiFIIPChangeListener(); +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP -#if CHIP_WITH_GIO - struct GDBusConnectionDeleter + class CallbackIndirection { - void operator()(GDBusConnection * conn) { g_object_unref(conn); } + public: + CallbackIndirection(GSourceFunc callback, void * userData) : mCallback(callback), mUserData(userData) {} + void Wait(std::unique_lock & lock); + static gboolean Callback(CallbackIndirection * self); + + private: + GSourceFunc mCallback; + void * mUserData; + // Sync primitives to wait for the callback to be executed. + std::condition_variable mDoneCond; + bool mDone = false; }; - using UniqueGDBusConnection = std::unique_ptr; - UniqueGDBusConnection mpGDBusConnection; -#endif + + // XXX: Mutex for guarding access to glib main event loop callback indirection + // synchronization primitives. This is a workaround to suppress TSAN warnings. + // TSAN does not know that from the thread synchronization perspective the + // g_source_attach() function should be treated as pthread_create(). Memory + // access to shared data before the call to g_source_attach() without mutex + // is not a race condition - the callback will not be executed on glib main + // event loop thread before the call to g_source_attach(). + std::mutex mGLibMainLoopCallbackIndirectionMutex; + + GMainLoop * mGLibMainLoop; + GThread * mGLibMainLoopThread; + +#endif // CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP }; /** diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.cpp b/src/platform/Linux/bluez/ChipDeviceScanner.cpp index 72b4e25a48c2ac..0d18e9273136af 100644 --- a/src/platform/Linux/bluez/ChipDeviceScanner.cpp +++ b/src/platform/Linux/bluez/ChipDeviceScanner.cpp @@ -19,14 +19,15 @@ #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE -#include "BluezObjectList.h" -#include "MainLoop.h" -#include "Types.h" - #include -#include #include +#include +#include + +#include "BluezObjectList.h" +#include "Types.h" + namespace chip { namespace DeviceLayer { namespace Internal { @@ -121,10 +122,8 @@ CHIP_ERROR ChipDeviceScanner::StartScan(System::Clock::Timeout timeout) { ReturnErrorCodeIf(mIsScanning, CHIP_ERROR_INCORRECT_STATE); - ReturnErrorOnFailure(MainLoop::Instance().EnsureStarted()); - mIsScanning = true; // optimistic, to allow all callbacks to check this - if (!MainLoop::Instance().ScheduleAndWait(MainLoopStartScan, this)) + if (PlatformMgrImpl().ScheduleOnGLibMainLoopThread(MainLoopStartScan, this, true) != CHIP_NO_ERROR) { ChipLogError(Ble, "Failed to schedule BLE scan start."); mIsScanning = false; @@ -173,7 +172,7 @@ CHIP_ERROR ChipDeviceScanner::StopScan() mInterfaceChangedSignal = 0; } - if (!MainLoop::Instance().ScheduleAndWait(MainLoopStopScan, this)) + if (PlatformMgrImpl().ScheduleOnGLibMainLoopThread(MainLoopStopScan, this, true) != CHIP_NO_ERROR) { ChipLogError(Ble, "Failed to schedule BLE scan stop."); return CHIP_ERROR_INTERNAL; diff --git a/src/platform/Linux/bluez/Helper.cpp b/src/platform/Linux/bluez/Helper.cpp index f65dbde49862f8..dbf088168e1fcc 100644 --- a/src/platform/Linux/bluez/Helper.cpp +++ b/src/platform/Linux/bluez/Helper.cpp @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -74,7 +75,6 @@ #include "BluezObjectIterator.h" #include "BluezObjectList.h" #include "Helper.h" -#include "MainLoop.h" using namespace ::nl; using namespace chip::Protocols; @@ -1191,18 +1191,15 @@ void EndpointCleanup(BluezEndpoint * apEndpoint) g_free(apEndpoint->mpPeerDevicePath); apEndpoint->mpPeerDevicePath = nullptr; } - g_free(apEndpoint->mpConnectCancellable); + if (apEndpoint->mpConnectCancellable != nullptr) + { + g_object_unref(apEndpoint->mpConnectCancellable); + apEndpoint->mpConnectCancellable = nullptr; + } g_free(apEndpoint); } } -int BluezObjectsCleanup(BluezEndpoint * apEndpoint) -{ - g_object_unref(apEndpoint->mpAdapter); - EndpointCleanup(apEndpoint); - return 0; -} - #if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING static void UpdateAdditionalDataCharacteristic(BluezGattCharacteristic1 * characteristic) { @@ -1377,11 +1374,6 @@ static int StartupEndpointBindings(BluezEndpoint * endpoint) g_signal_connect(manager, "object-removed", G_CALLBACK(BluezSignalOnObjectRemoved), endpoint); g_signal_connect(manager, "interface-proxy-properties-changed", G_CALLBACK(BluezSignalInterfacePropertiesChanged), endpoint); - if (!MainLoop::Instance().SetCleanupFunction(BluezObjectsCleanup, endpoint)) - { - ChipLogError(DeviceLayer, "Failed to schedule cleanup function"); - } - exit: if (error != nullptr) g_error_free(error); @@ -1444,16 +1436,10 @@ static ConnectionDataBundle * MakeConnectionDataBundle(BLE_CONNECTION_OBJECT apC return bundle; } -bool SendBluezIndication(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf) +CHIP_ERROR SendBluezIndication(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf) { - bool success = false; - - VerifyOrExit(!apBuf.IsNull(), ChipLogError(DeviceLayer, "apBuf is NULL in %s", __func__)); - - success = MainLoop::Instance().Schedule(BluezC2Indicate, MakeConnectionDataBundle(apConn, apBuf)); - -exit: - return success; + VerifyOrReturnError(!apBuf.IsNull(), (ChipLogError(DeviceLayer, "apBuf is NULL in %s", __func__), CHIP_ERROR_INVALID_ARGUMENT)); + return PlatformMgrImpl().ScheduleOnGLibMainLoopThread(BluezC2Indicate, MakeConnectionDataBundle(apConn, apBuf)); } static gboolean BluezDisconnect(void * apClosure) @@ -1482,52 +1468,41 @@ static int CloseBleconnectionCB(void * apAppState) return G_SOURCE_REMOVE; } -bool CloseBluezConnection(BLE_CONNECTION_OBJECT apConn) +CHIP_ERROR CloseBluezConnection(BLE_CONNECTION_OBJECT apConn) { - return MainLoop::Instance().RunOnBluezThread(CloseBleconnectionCB, apConn); + return PlatformMgrImpl().ScheduleOnGLibMainLoopThread(CloseBleconnectionCB, apConn); } CHIP_ERROR StartBluezAdv(BluezEndpoint * apEndpoint) { - CHIP_ERROR err = CHIP_NO_ERROR; - if (!MainLoop::Instance().Schedule(BluezAdvStart, apEndpoint)) - { - err = CHIP_ERROR_INCORRECT_STATE; - ChipLogError(Ble, "Failed to schedule BluezAdvStart() on CHIPoBluez thread"); - } + CHIP_ERROR err = PlatformMgrImpl().ScheduleOnGLibMainLoopThread(BluezAdvStart, apEndpoint); + VerifyOrReturnError(err == CHIP_NO_ERROR, + (ChipLogError(Ble, "Failed to schedule BluezAdvStart() on CHIPoBluez thread"), CHIP_ERROR_INCORRECT_STATE)); return err; } CHIP_ERROR StopBluezAdv(BluezEndpoint * apEndpoint) { - CHIP_ERROR err = CHIP_NO_ERROR; - if (!MainLoop::Instance().Schedule(BluezAdvStop, apEndpoint)) - { - err = CHIP_ERROR_INCORRECT_STATE; - ChipLogError(Ble, "Failed to schedule BluezAdvStop() on CHIPoBluez thread"); - } + CHIP_ERROR err = PlatformMgrImpl().ScheduleOnGLibMainLoopThread(BluezAdvStop, apEndpoint); + VerifyOrReturnError(err == CHIP_NO_ERROR, + (ChipLogError(Ble, "Failed to schedule BluezAdvStop() on CHIPoBluez thread"), CHIP_ERROR_INCORRECT_STATE)); return err; } CHIP_ERROR BluezAdvertisementSetup(BluezEndpoint * apEndpoint) { - CHIP_ERROR err = CHIP_NO_ERROR; - if (!MainLoop::Instance().Schedule(BluezAdvSetup, apEndpoint)) - { - err = CHIP_ERROR_INCORRECT_STATE; - ChipLogError(Ble, "Failed to schedule BluezAdvertisementSetup() on CHIPoBluez thread"); - } + CHIP_ERROR err = PlatformMgrImpl().ScheduleOnGLibMainLoopThread(BluezAdvSetup, apEndpoint); + VerifyOrReturnError(err == CHIP_NO_ERROR, + (ChipLogError(Ble, "Failed to schedule BluezAdvSetup() on CHIPoBluez thread"), CHIP_ERROR_INCORRECT_STATE)); return err; } CHIP_ERROR BluezGattsAppRegister(BluezEndpoint * apEndpoint) { - CHIP_ERROR err = CHIP_NO_ERROR; - if (!MainLoop::Instance().Schedule(BluezPeripheralRegisterApp, apEndpoint)) - { - err = CHIP_ERROR_INCORRECT_STATE; - ChipLogError(Ble, "Failed to schedule BluezPeripheralRegisterApp() on CHIPoBluez thread"); - } + CHIP_ERROR err = PlatformMgrImpl().ScheduleOnGLibMainLoopThread(BluezPeripheralRegisterApp, apEndpoint); + VerifyOrReturnError( + err == CHIP_NO_ERROR, + (ChipLogError(Ble, "Failed to schedule BluezPeripheralRegisterApp() on CHIPoBluez thread"), CHIP_ERROR_INCORRECT_STATE)); return err; } @@ -1590,14 +1565,8 @@ CHIP_ERROR InitBluezBleLayer(bool aIsCentral, char * apBleAddr, BLEAdvConfig & a endpoint->mpConnectCancellable = g_cancellable_new(); } - err = MainLoop::Instance().EnsureStarted(); - VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "Failed to start BLE main loop")); - - if (!MainLoop::Instance().ScheduleAndWait(StartupEndpointBindings, endpoint)) - { - ChipLogError(DeviceLayer, "Failed to schedule endpoint initialization"); - ExitNow(); - } + err = PlatformMgrImpl().ScheduleOnGLibMainLoopThread(StartupEndpointBindings, endpoint, true); + VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(DeviceLayer, "Failed to schedule endpoint initialization")); retval = TRUE; @@ -1615,6 +1584,14 @@ CHIP_ERROR InitBluezBleLayer(bool aIsCentral, char * apBleAddr, BLEAdvConfig & a return err; } +CHIP_ERROR ShutdownBluezBleLayer(BluezEndpoint * apEndpoint) +{ + VerifyOrReturnError(apEndpoint != nullptr, CHIP_ERROR_INVALID_ARGUMENT); + g_object_unref(apEndpoint->mpAdapter); + EndpointCleanup(apEndpoint); + return CHIP_NO_ERROR; +} + // BluezSendWriteRequest callbacks static void SendWriteRequestDone(GObject * aObject, GAsyncResult * aResult, gpointer apConnection) @@ -1631,10 +1608,9 @@ static void SendWriteRequestDone(GObject * aObject, GAsyncResult * aResult, gpoi g_error_free(error); } -static gboolean SendWriteRequestImpl(void * apConnectionData) +static gboolean SendWriteRequestImpl(ConnectionDataBundle * data) { - ConnectionDataBundle * data = static_cast(apConnectionData); - GVariant * options = nullptr; + GVariant * options = nullptr; GVariantBuilder optionsBuilder; VerifyOrExit(data != nullptr, ChipLogError(DeviceLayer, "ConnectionDataBundle is NULL in %s", __func__)); @@ -1653,16 +1629,10 @@ static gboolean SendWriteRequestImpl(void * apConnectionData) return G_SOURCE_REMOVE; } -bool BluezSendWriteRequest(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf) +CHIP_ERROR BluezSendWriteRequest(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf) { - bool success = false; - - VerifyOrExit(!apBuf.IsNull(), ChipLogError(DeviceLayer, "apBuf is NULL in %s", __func__)); - - success = MainLoop::Instance().RunOnBluezThread(SendWriteRequestImpl, MakeConnectionDataBundle(apConn, apBuf)); - -exit: - return success; + VerifyOrReturnError(!apBuf.IsNull(), (ChipLogError(DeviceLayer, "apBuf is NULL in %s", __func__), CHIP_ERROR_INVALID_ARGUMENT)); + return PlatformMgrImpl().ScheduleOnGLibMainLoopThread(SendWriteRequestImpl, MakeConnectionDataBundle(apConn, apBuf)); } // BluezSubscribeCharacteristic callbacks @@ -1711,9 +1681,9 @@ static gboolean SubscribeCharacteristicImpl(BluezConnection * connection) return G_SOURCE_REMOVE; } -bool BluezSubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn) +CHIP_ERROR BluezSubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn) { - return MainLoop::Instance().Schedule(SubscribeCharacteristicImpl, static_cast(apConn)); + return PlatformMgrImpl().ScheduleOnGLibMainLoopThread(SubscribeCharacteristicImpl, static_cast(apConn)); } // BluezUnsubscribeCharacteristic callbacks @@ -1746,9 +1716,9 @@ static gboolean UnsubscribeCharacteristicImpl(BluezConnection * connection) return G_SOURCE_REMOVE; } -bool BluezUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn) +CHIP_ERROR BluezUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn) { - return MainLoop::Instance().Schedule(UnsubscribeCharacteristicImpl, static_cast(apConn)); + return PlatformMgrImpl().ScheduleOnGLibMainLoopThread(UnsubscribeCharacteristicImpl, static_cast(apConn)); } // ConnectDevice callbacks @@ -1823,7 +1793,7 @@ CHIP_ERROR ConnectDevice(BluezDevice1 * apDevice, BluezEndpoint * apEndpoint) auto params = chip::Platform::New(apDevice, apEndpoint); g_object_ref(apDevice); - if (!MainLoop::Instance().Schedule(ConnectDeviceImpl, params)) + if (PlatformMgrImpl().ScheduleOnGLibMainLoopThread(ConnectDeviceImpl, params) != CHIP_NO_ERROR) { ChipLogError(Ble, "Failed to schedule ConnectDeviceImpl() on CHIPoBluez thread"); g_object_unref(apDevice); diff --git a/src/platform/Linux/bluez/Helper.h b/src/platform/Linux/bluez/Helper.h index e77ffc96ef1a3c..d2576e019751ba 100644 --- a/src/platform/Linux/bluez/Helper.h +++ b/src/platform/Linux/bluez/Helper.h @@ -59,20 +59,20 @@ namespace DeviceLayer { namespace Internal { CHIP_ERROR InitBluezBleLayer(bool aIsCentral, char * apBleAddr, BLEAdvConfig & aBleAdvConfig, BluezEndpoint *& apEndpoint); -bool BluezRunOnBluezThread(int (*aCallback)(void *), void * apClosure); -bool SendBluezIndication(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf); -bool CloseBluezConnection(BLE_CONNECTION_OBJECT apConn); +CHIP_ERROR ShutdownBluezBleLayer(BluezEndpoint * apEndpoint); +CHIP_ERROR SendBluezIndication(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf); +CHIP_ERROR CloseBluezConnection(BLE_CONNECTION_OBJECT apConn); CHIP_ERROR StartBluezAdv(BluezEndpoint * apEndpoint); CHIP_ERROR StopBluezAdv(BluezEndpoint * apEndpoint); CHIP_ERROR BluezGattsAppRegister(BluezEndpoint * apEndpoint); CHIP_ERROR BluezAdvertisementSetup(BluezEndpoint * apEndpoint); /// Write to the CHIP RX characteristic on the remote peripheral device -bool BluezSendWriteRequest(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf); +CHIP_ERROR BluezSendWriteRequest(BLE_CONNECTION_OBJECT apConn, chip::System::PacketBufferHandle apBuf); /// Subscribe to the CHIP TX characteristic on the remote peripheral device -bool BluezSubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn); +CHIP_ERROR BluezSubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn); /// Unsubscribe from the CHIP TX characteristic on the remote peripheral device -bool BluezUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn); +CHIP_ERROR BluezUnsubscribeCharacteristic(BLE_CONNECTION_OBJECT apConn); CHIP_ERROR ConnectDevice(BluezDevice1 * apDevice, BluezEndpoint * apEndpoint); void CancelConnect(BluezEndpoint * apEndpoint); diff --git a/src/platform/Linux/bluez/MainLoop.cpp b/src/platform/Linux/bluez/MainLoop.cpp deleted file mode 100644 index 64320f5cfa674b..00000000000000 --- a/src/platform/Linux/bluez/MainLoop.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2021 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "MainLoop.h" - -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - -#include -#include -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Internal { - -namespace { - -class Semaphore -{ -public: - Semaphore() - { - if (sem_init(&mSemaphore, 0 /* shared */, 0 /*value*/) != 0) - { - ChipLogError(DeviceLayer, "Failed to initialize semaphore."); - } - } - - ~Semaphore() - { - if (sem_destroy(&mSemaphore) != 0) - { - ChipLogError(DeviceLayer, "Failed to destroy semaphore."); - } - } - - void Post() { sem_post(&mSemaphore); } - - void Wait() { sem_wait(&mSemaphore); } - -private: - sem_t mSemaphore; -}; - -int PostSemaphore(Semaphore * semaphore) -{ - semaphore->Post(); - return 0; -} - -class CallbackIndirection -{ -public: - CallbackIndirection(GSourceFunc f, void * a) : mCallback(f), mArgument(a) {} - - void Wait() { mDoneSemaphore.Wait(); } - - static int Callback(CallbackIndirection * self) - { - int result = self->mCallback(self->mArgument); - self->mDoneSemaphore.Post(); - return result; - } - -private: - Semaphore mDoneSemaphore; - GSourceFunc mCallback; - void * mArgument; -}; - -} // namespace - -MainLoop & MainLoop::Instance() -{ - static MainLoop sMainLoop; - return sMainLoop; -} - -void * MainLoop::Thread(void * self) -{ - MainLoop * loop = reinterpret_cast(self); - - ChipLogDetail(DeviceLayer, "TRACE: Bluez mainloop starting %s", __func__); - g_main_loop_run(loop->mBluezMainLoop); - ChipLogDetail(DeviceLayer, "TRACE: Bluez mainloop stopping %s", __func__); - - if (loop->mCleanup != nullptr) - { - ChipLogDetail(DeviceLayer, "TRACE: Executing cleanup %s", __func__); - loop->mCleanup(loop->mCleanupArgument); - } - - return nullptr; -} - -CHIP_ERROR MainLoop::EnsureStarted() -{ - if (mBluezMainLoop != nullptr) - { - return CHIP_NO_ERROR; - } - - mBluezMainLoop = g_main_loop_new(nullptr, TRUE); - if (mBluezMainLoop == nullptr) - { - ChipLogError(DeviceLayer, "FAIL: memory alloc in %s", __func__); - return CHIP_ERROR_NO_MEMORY; - } - - int pthreadErr = pthread_create(&mThread, nullptr, &MainLoop::Thread, reinterpret_cast(this)); -#if CHIP_ERROR_LOGGING - int tmpErrno = errno; -#endif // CHIP_ERROR_LOGGING - if (pthreadErr != 0) - { - ChipLogError(DeviceLayer, "FAIL: pthread_create (%s) in %s", strerror(tmpErrno), __func__); - g_free(mBluezMainLoop); - mBluezMainLoop = nullptr; - return CHIP_ERROR_INTERNAL; - } - - Semaphore semaphore; - - GMainContext * context = g_main_loop_get_context(mBluezMainLoop); - VerifyOrDie(context != nullptr); - - g_main_context_invoke(context, GSourceFunc(PostSemaphore), &semaphore); - - semaphore.Wait(); - - return CHIP_NO_ERROR; -} - -bool MainLoop::RunOnBluezThread(GSourceFunc callback, void * argument) -{ - GMainContext * context = nullptr; - const char * msg = nullptr; - - VerifyOrExit(mBluezMainLoop != nullptr, msg = "FAIL: NULL sBluezMainLoop"); - VerifyOrExit(g_main_loop_is_running(mBluezMainLoop), msg = "FAIL: sBluezMainLoop not running"); - - context = g_main_loop_get_context(mBluezMainLoop); - VerifyOrExit(context != nullptr, msg = "FAIL: NULL main context"); - g_main_context_invoke(context, callback, argument); - -exit: - if (msg != nullptr) - { - ChipLogDetail(DeviceLayer, "%s in %s", msg, __func__); - } - - return msg == nullptr; -} - -bool MainLoop::RunOnBluezThreadAndWait(GSourceFunc closure, void * argument) -{ - CallbackIndirection indirection(closure, argument); - - if (!Schedule(&CallbackIndirection::Callback, &indirection)) - { - return false; - } - - indirection.Wait(); - - return true; -} - -} // namespace Internal -} // namespace DeviceLayer -} // namespace chip - -#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/Linux/bluez/MainLoop.h b/src/platform/Linux/bluez/MainLoop.h deleted file mode 100644 index e2a06e13122686..00000000000000 --- a/src/platform/Linux/bluez/MainLoop.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2021 Project CHIP Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include -#include - -#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE - -#include -#include - -namespace chip { -namespace DeviceLayer { -namespace Internal { - -/// The main loop provides a thread-based implementation that runs -/// the GLib main loop. -/// -/// The main loop is used execute callbacks (e.g. dbus notifications). -class MainLoop -{ -public: - /// Ensure that a thread with g_main_loop_run is executing. - CHIP_ERROR EnsureStarted(); - - /// Executes a callback on the underlying main loop. - /// - /// The main loop MUST have been started already. - bool RunOnBluezThread(GSourceFunc closure, void * arg); - - /// Executes a callback on the underlying main loop and waits for - /// the method to complete. - /// - /// The main loop MUST have been started already. - bool RunOnBluezThreadAndWait(GSourceFunc closure, void * arg); - - /// Convenience method to require less casts to void* - template - bool Schedule(int (*callback)(T *), T * value) - { - return RunOnBluezThread(G_SOURCE_FUNC(callback), value); - } - - /// Convenience method to require less casts to void* - template - bool ScheduleAndWait(int (*callback)(T *), T * value) - { - return RunOnBluezThreadAndWait(G_SOURCE_FUNC(callback), value); - } - - /// Schedules a method to be executed after the main loop has finished - /// - /// A single cleanup method can exist and the main loop has to be running - /// to set a cleanup method. - template - bool SetCleanupFunction(int (*callback)(T *), T * value) - { - if (mCleanup != nullptr) - { - return false; - } - - if ((mBluezMainLoop == nullptr) || !g_main_loop_is_running(mBluezMainLoop)) - { - return false; - } - - mCleanup = G_SOURCE_FUNC(callback); - mCleanupArgument = static_cast(value); - - return true; - } - - static MainLoop & Instance(); - -private: - MainLoop() {} - - static void * Thread(void * self); - - GMainLoop * mBluezMainLoop = nullptr; - pthread_t mThread = 0; - - // allow a single cleanup method - GSourceFunc mCleanup = nullptr; - void * mCleanupArgument = nullptr; -}; - -} // namespace Internal -} // namespace DeviceLayer -} // namespace chip - -#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE diff --git a/src/platform/android/PlatformManagerImpl.h b/src/platform/android/PlatformManagerImpl.h index 4771fa9b5c5e73..af577ed10b016c 100644 --- a/src/platform/android/PlatformManagerImpl.h +++ b/src/platform/android/PlatformManagerImpl.h @@ -46,7 +46,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener public: // ===== Platform-specific members that may be accessed directly by the application. - // Post SystemEvent from Java, like WiFIIPChangeListener in Linux Platform + // Post SystemEvent from Java, like WiFiIPChangeListener in Linux Platform // void PostJavaEvent(); private: diff --git a/src/platform/webos/CHIPDevicePlatformConfig.h b/src/platform/webos/CHIPDevicePlatformConfig.h index 88a9bc647e25ff..cd5e734c233777 100644 --- a/src/platform/webos/CHIPDevicePlatformConfig.h +++ b/src/platform/webos/CHIPDevicePlatformConfig.h @@ -41,6 +41,14 @@ #define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 0 #endif +// Start GLib main event loop if WiFi is enabled. This is needed to handle +// D-Bus communication with wpa_supplicant. +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI +#define CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 1 +#else +#define CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP 0 +#endif + // ========== Platform-specific Configuration ========= // These are configuration options that are unique to webOS platforms. diff --git a/src/platform/webos/PlatformManagerImpl.cpp b/src/platform/webos/PlatformManagerImpl.cpp index 299c62dfa72e0c..fb353702ad622f 100644 --- a/src/platform/webos/PlatformManagerImpl.cpp +++ b/src/platform/webos/PlatformManagerImpl.cpp @@ -24,6 +24,17 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + #include #include #include @@ -35,22 +46,6 @@ #include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 30 -#include -#define gettid() syscall(SYS_gettid) -#endif - using namespace ::chip::app::Clusters; namespace chip { @@ -60,19 +55,18 @@ PlatformManagerImpl PlatformManagerImpl::sInstance; namespace { -#if CHIP_WITH_GIO -void GDBus_Thread() +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP +void * GLibMainLoopThread(void * loop) { - GMainLoop * loop = g_main_loop_new(nullptr, false); - - g_main_loop_run(loop); - g_main_loop_unref(loop); + g_main_loop_run(static_cast(loop)); + return nullptr; } #endif + } // namespace #if CHIP_DEVICE_CONFIG_ENABLE_WIFI -void PlatformManagerImpl::WiFIIPChangeListener() +void PlatformManagerImpl::WiFiIPChangeListener() { int sock; if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) @@ -148,17 +142,13 @@ void PlatformManagerImpl::WiFIIPChangeListener() CHIP_ERROR PlatformManagerImpl::_InitChipStack() { -#if CHIP_WITH_GIO - GError * error = nullptr; - - this->mpGDBusConnection = UniqueGDBusConnection(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error)); - - std::thread gdbusThread(GDBus_Thread); - gdbusThread.detach(); +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP + mGLibMainLoop = g_main_loop_new(nullptr, FALSE); + mGLibMainLoopThread = g_thread_new("gmain-matter", GLibMainLoopThread, mGLibMainLoop); #endif #if CHIP_DEVICE_CONFIG_ENABLE_WIFI - std::thread wifiIPThread(WiFIIPChangeListener); + std::thread wifiIPThread(WiFiIPChangeListener); wifiIPThread.detach(); #endif @@ -201,14 +191,13 @@ void PlatformManagerImpl::_Shutdown() } Internal::GenericPlatformManagerImpl_POSIX::_Shutdown(); -} -#if CHIP_WITH_GIO -GDBusConnection * PlatformManagerImpl::GetGDBusConnection() -{ - return this->mpGDBusConnection.get(); -} +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP + g_main_loop_quit(mGLibMainLoop); + g_main_loop_unref(mGLibMainLoop); + g_thread_join(mGLibMainLoopThread); #endif +} } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/webos/PlatformManagerImpl.h b/src/platform/webos/PlatformManagerImpl.h index 9594cff6b91c4c..a46b1068345dc5 100644 --- a/src/platform/webos/PlatformManagerImpl.h +++ b/src/platform/webos/PlatformManagerImpl.h @@ -26,7 +26,7 @@ #include #include -#if CHIP_WITH_GIO +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP #include #endif @@ -50,9 +50,6 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener public: // ===== Platform-specific members that may be accessed directly by the application. -#if CHIP_WITH_GIO - GDBusConnection * GetGDBusConnection(); -#endif System::Clock::Timestamp GetStartTime() { return mStartTime; } @@ -72,17 +69,15 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener static PlatformManagerImpl sInstance; +#if CHIP_DEVICE_CONFIG_ENABLE_WIFI // The temporary hack for getting IP address change on linux for network provisioning in the rendezvous session. - // This should be removed or find a better place once we depercate the rendezvous session. - static void WiFIIPChangeListener(); - -#if CHIP_WITH_GIO - struct GDBusConnectionDeleter - { - void operator()(GDBusConnection * conn) { g_object_unref(conn); } - }; - using UniqueGDBusConnection = std::unique_ptr; - UniqueGDBusConnection mpGDBusConnection; + // This should be removed or find a better place once we deprecate the rendezvous session. + static void WiFiIPChangeListener(); +#endif + +#if CHIP_DEVICE_CONFIG_WITH_GLIB_MAIN_LOOP + GMainLoop * mGLibMainLoop; + GThread * mGLibMainLoopThread; #endif };