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