From af3727badd0fcdf9540d8e8b36eef2cfdf87f14b Mon Sep 17 00:00:00 2001 From: Vivien Nicolas Date: Wed, 9 Oct 2024 02:20:27 +0200 Subject: [PATCH] =?UTF-8?q?[Matter.framework]=20Prevent=20a=20leak=20when?= =?UTF-8?q?=20using=20the=20=5FsubscriptionPoolWor=E2=80=A6=20(#35978)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/darwin/Framework/CHIP/MTRDevice_Concrete.mm | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm index 125ced558eb961..947e7a39679260 100644 --- a/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm +++ b/src/darwin/Framework/CHIP/MTRDevice_Concrete.mm @@ -757,7 +757,9 @@ - (void)_ensureSubscriptionForExistingDelegates:(NSString *)reason } if ([self _deviceUsesThread]) { MTR_LOG(" => %@ - device is a thread device, scheduling in pool", self); + mtr_weakify(self); [self _scheduleSubscriptionPoolWork:^{ + mtr_strongify(self); [self->_deviceController asyncDispatchToMatterQueue:^{ std::lock_guard lock(self->_lock); [self _setupSubscriptionWithReason:[NSString stringWithFormat:@"%@ and scheduled subscription is happening", reason]]; @@ -1165,10 +1167,13 @@ - (void)_scheduleSubscriptionPoolWork:(dispatch_block_t)workBlock inNanoseconds: return; } + mtr_weakify(self); dispatch_block_t workBlockToQueue = ^{ + mtr_strongify(self); // In the case where a resubscription triggering event happened and already established, running the work block should result in a no-op MTRAsyncWorkItem * workItem = [[MTRAsyncWorkItem alloc] initWithQueue:self.queue]; [workItem setReadyHandler:^(id _Nonnull context, NSInteger retryCount, MTRAsyncWorkCompletionBlock _Nonnull completion) { + mtr_strongify(self); MTR_LOG("%@ - work item is ready to attempt pooled subscription", self); os_unfair_lock_lock(&self->_lock); #ifdef DEBUG @@ -1246,7 +1251,9 @@ - (void)_handleResubscriptionNeededWithDelayOnDeviceQueue:(NSNumber *)resubscrip // Use the existing _triggerResubscribeWithReason mechanism, which does the right checks when // this block is run -- if other triggering events had happened, this would become a no-op. + mtr_weakify(self); auto resubscriptionBlock = ^{ + mtr_strongify(self); [self->_deviceController asyncDispatchToMatterQueue:^{ [self _triggerResubscribeWithReason:@"ResubscriptionNeeded timer fired" nodeLikelyReachable:NO]; } errorHandler:^(NSError * _Nonnull error) { @@ -1357,7 +1364,9 @@ - (void)_doHandleSubscriptionReset:(NSNumber * _Nullable)retryDelay // Call _reattemptSubscriptionNowIfNeededWithReason when timer fires - if subscription is // in a better state at that time this will be a no-op. + mtr_weakify(self); auto resubscriptionBlock = ^{ + mtr_strongify(self); [self->_deviceController asyncDispatchToMatterQueue:^{ std::lock_guard lock(self->_lock); [self _reattemptSubscriptionNowIfNeededWithReason:@"got subscription reset"];