From 10399763f7643f9c9b4b36503251ae9e8020d385 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 31 Jan 2023 21:04:11 -0500 Subject: [PATCH] Call stopControllerFactory atexit in the Darwin framework. (#24767) We have lots of things with static destructors that assert clean shutdown in the destructor. That means that calling exit() without a clean shutdown is pretty much guaranteed to lead to a shutdown crash. Just ensure that we are in fact shutting down the MTRDeviceControllerFactory if exit() is called, to avoid those crashes. Fixes https://github.com/project-chip/connectedhomeip/issues/14859 --- .../Framework/CHIP/MTRDeviceControllerFactory.mm | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm index d0040a2caf54ba..885b118a31cc65 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm @@ -44,6 +44,8 @@ #include #include +#include + using namespace chip; using namespace chip::Controller; @@ -58,6 +60,9 @@ static NSString * const kErrorCDCertStoreInit = @"Init failure while initializing Certificate Declaration Signing Keys store"; static NSString * const kErrorOtaProviderInit = @"Init failure while creating an OTA provider delegate"; +static bool sExitHandlerRegistered = false; +static void ShutdownOnExit() { [[MTRDeviceControllerFactory sharedInstance] stopControllerFactory]; } + @interface MTRDeviceControllerFactory () @property (atomic, readonly) dispatch_queue_t chipWorkQueue; @@ -382,7 +387,14 @@ - (BOOL)startControllerFactory:(MTRDeviceControllerFactoryParams *)startupParams // This needs to happen after DeviceControllerFactory::Init, // because that creates (lazily, by calling functions with // static variables in them) some static-lifetime objects. - chip::HeapObjectPoolExitHandling::IgnoreLeaksOnExit(); + if (!sExitHandlerRegistered) { + int ret = atexit(ShutdownOnExit); + if (ret != 0) { + MTR_LOG_ERROR("Error registering exit handler: %d", ret); + return; + } + } + HeapObjectPoolExitHandling::IgnoreLeaksOnExit(); // Make sure we don't leave a system state running while we have no // controllers started. This is working around the fact that a system