From 21643547801288e64c6c83b2f6e9c29bdc1712a9 Mon Sep 17 00:00:00 2001 From: Jeff Tung <100387939+jtung-apple@users.noreply.github.com> Date: Mon, 3 Oct 2022 10:19:25 -0700 Subject: [PATCH] Issue #22935 [Darwin] MTRBaseSubscriptionCallback OnDone callback being called async can lead to crashes (#22978) --- .../CHIP/MTRBaseSubscriptionCallback.mm | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/darwin/Framework/CHIP/MTRBaseSubscriptionCallback.mm b/src/darwin/Framework/CHIP/MTRBaseSubscriptionCallback.mm index 60dd3b9dde3aba..564c6a357d0e2b 100644 --- a/src/darwin/Framework/CHIP/MTRBaseSubscriptionCallback.mm +++ b/src/darwin/Framework/CHIP/MTRBaseSubscriptionCallback.mm @@ -138,12 +138,21 @@ mOnDoneHandler = nil; dispatch_async(mQueue, ^{ callback(err); - if (onDoneHandler) { - onDoneHandler(); - } }); - if (aCancelSubscription) { + if (onDoneHandler) { + // To guarantee the async onDoneHandler call is made before + // deletion, so that clean up can happen while the callback + // object is still alive (and therefore cluster cache), queue + // deletion after calling the onDoneHandler + mHaveQueuedDeletion = true; + dispatch_async(mQueue, ^{ + onDoneHandler(); + dispatch_async(DeviceLayer::PlatformMgrImpl().GetWorkQueue(), ^{ + delete myself; + }); + }); + } else if (aCancelSubscription) { // We can't synchronously delete ourselves, because we're inside one of // the ReadClient callbacks and we need to outlive the callback's // execution. Queue an async deletion on the Matter queue (where we are