diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp index 5374adaacc40b0..e53b854ecbb8a6 100644 --- a/examples/chip-tool/commands/common/Commands.cpp +++ b/examples/chip-tool/commands/common/Commands.cpp @@ -85,8 +85,6 @@ int Commands::Run(NodeId localId, NodeId remoteId, int argc, char ** argv) // since the CHIP thread and event queue have been stopped, preventing any thread // races. // - // TODO: This doesn't hold true on Darwin, issue #7557 tracks the problem. - // mController.Shutdown(); return (err == CHIP_NO_ERROR) ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/src/darwin/Framework/CHIP/CHIPDeviceController.mm b/src/darwin/Framework/CHIP/CHIPDeviceController.mm index 85dbede0828e78..c9d264dff5c152 100644 --- a/src/darwin/Framework/CHIP/CHIPDeviceController.mm +++ b/src/darwin/Framework/CHIP/CHIPDeviceController.mm @@ -118,20 +118,25 @@ - (BOOL)_isRunning - (BOOL)shutdown { - dispatch_sync(_chipWorkQueue, ^{ - if (_cppCommissioner) { + dispatch_async(_chipWorkQueue, ^{ + if (self->_cppCommissioner) { CHIP_LOG_DEBUG("%@", kInfoStackShutdown); - _cppCommissioner->Shutdown(); - delete _cppCommissioner; - _cppCommissioner = nullptr; + self->_cppCommissioner->Shutdown(); + delete self->_cppCommissioner; + self->_cppCommissioner = nullptr; } }); + // StopEventLoopTask will block until blocks are executed + chip::DeviceLayer::PlatformMgrImpl().StopEventLoopTask(); + return YES; } - (BOOL)startup:(_Nullable id)storageDelegate { + chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask(); + __block BOOL commissionerInitialized = NO; dispatch_sync(_chipWorkQueue, ^{ if ([self _isRunning]) { @@ -176,8 +181,6 @@ - (BOOL)startup:(_Nullable id)storageDelegate return; } - // Start the IO pump - self.cppCommissioner->ServiceEvents(); commissionerInitialized = YES; }); diff --git a/src/platform/Darwin/PlatformManagerImpl.cpp b/src/platform/Darwin/PlatformManagerImpl.cpp index 18168617922d9b..4eb375e85faa6e 100644 --- a/src/platform/Darwin/PlatformManagerImpl.cpp +++ b/src/platform/Darwin/PlatformManagerImpl.cpp @@ -29,6 +29,8 @@ // Include the non-inline definitions for the GenericPlatformManagerImpl<> template, #include +#include + namespace chip { namespace DeviceLayer { @@ -53,6 +55,40 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack() return err; } +CHIP_ERROR PlatformManagerImpl::_StartEventLoopTask() +{ + if (mIsWorkQueueRunning == false) + { + mIsWorkQueueRunning = true; + dispatch_resume(mWorkQueue); + } + + return CHIP_NO_ERROR; +}; + +CHIP_ERROR PlatformManagerImpl::_StopEventLoopTask() +{ + + if (mIsWorkQueueRunning == true) + { + mIsWorkQueueRunning = false; + + // dispatch_sync is used in order to guarantee serialization of the caller with + // respect to any tasks that might already be on the queue, or running. + dispatch_sync(mWorkQueue, ^{ + dispatch_suspend(mWorkQueue); + }); + } + + return CHIP_NO_ERROR; +}; + +void PlatformManagerImpl::_RunEventLoop() +{ + _StartEventLoopTask(); + CFRunLoopRun(); +}; + CHIP_ERROR PlatformManagerImpl::_Shutdown() { // Call up to the base class _Shutdown() to perform the bulk of the shutdown. diff --git a/src/platform/Darwin/PlatformManagerImpl.h b/src/platform/Darwin/PlatformManagerImpl.h index 48fac0169544b9..651092ffd74a03 100644 --- a/src/platform/Darwin/PlatformManagerImpl.h +++ b/src/platform/Darwin/PlatformManagerImpl.h @@ -48,6 +48,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener if (mWorkQueue == nullptr) { mWorkQueue = dispatch_queue_create(CHIP_CONTROLLER_QUEUE, DISPATCH_QUEUE_SERIAL); + dispatch_suspend(mWorkQueue); } return mWorkQueue; } @@ -58,9 +59,9 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener CHIP_ERROR _Shutdown(); CHIP_ERROR _StartChipTimer(int64_t aMilliseconds) { return CHIP_ERROR_NOT_IMPLEMENTED; }; - CHIP_ERROR _StartEventLoopTask() { return CHIP_NO_ERROR; }; - CHIP_ERROR _StopEventLoopTask() { return CHIP_NO_ERROR; }; - void _RunEventLoop(){}; + CHIP_ERROR _StartEventLoopTask(); + CHIP_ERROR _StopEventLoopTask(); + void _RunEventLoop(); void _LockChipStack(){}; bool _TryLockChipStack() { return false; }; void _UnlockChipStack(){}; @@ -79,6 +80,7 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener static PlatformManagerImpl sInstance; dispatch_queue_t mWorkQueue = nullptr; + bool mIsWorkQueueRunning = false; inline ImplClass * Impl() { return static_cast(this); } };