Skip to content

Commit 3d434c3

Browse files
Avoid capturing this in MTRCommissionableBrowser dispatches (#38158)
Also hold MTRDeviceController reference weakly.
1 parent 9cfffb8 commit 3d434c3

File tree

1 file changed

+36
-21
lines changed

1 file changed

+36
-21
lines changed

src/darwin/Framework/CHIP/MTRCommissionableBrowser.mm

+36-21
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ CHIP_ERROR Start(id<MTRCommissionableBrowserDelegate> delegate, MTRDeviceControl
7979
VerifyOrReturnError(mDispatchQueue == nil, CHIP_ERROR_INCORRECT_STATE);
8080
VerifyOrReturnError(mDiscoveredResults == nil, CHIP_ERROR_INCORRECT_STATE);
8181

82+
VerifyOrReturnError(delegate != nil, CHIP_ERROR_INVALID_ARGUMENT);
83+
VerifyOrReturnError(controller != nil, CHIP_ERROR_INVALID_ARGUMENT);
84+
VerifyOrReturnError(queue != nil, CHIP_ERROR_INVALID_ARGUMENT);
85+
8286
mDelegate = delegate;
8387
mController = controller;
8488
mDispatchQueue = queue;
@@ -173,6 +177,11 @@ void OnNodeDiscovered(const DiscoveredNodeData & nodeData) override
173177
{
174178
assertChipStackLockedByCurrentThread();
175179

180+
// Copy delegate and controller to the stack to avoid capturing `this` in the dispatch_async
181+
id<MTRCommissionableBrowserDelegate> delegate = mDelegate;
182+
MTRDeviceController * controller = mController;
183+
VerifyOrReturn(delegate != nil && controller != nil);
184+
176185
if (!nodeData.Is<CommissionNodeData>()) {
177186
// not commissionable/commissioners node
178187
return;
@@ -207,13 +216,10 @@ void OnNodeDiscovered(const DiscoveredNodeData & nodeData) override
207216
break;
208217
}
209218
}
210-
211-
if (!shouldDispatchToDelegate) {
212-
return;
213-
}
219+
VerifyOrReturn(shouldDispatchToDelegate);
214220

215221
dispatch_async(mDispatchQueue, ^{
216-
[mDelegate controller:mController didFindCommissionableDevice:result];
222+
[delegate controller:controller didFindCommissionableDevice:result];
217223
});
218224
}
219225

@@ -245,9 +251,10 @@ void OnBrowseRemove(DnssdService service) override
245251
{
246252
assertChipStackLockedByCurrentThread();
247253

248-
VerifyOrReturn(mDelegate != nil);
249-
VerifyOrReturn(mController != nil);
250-
VerifyOrReturn(mDispatchQueue != nil);
254+
// Copy delegate and controller to the stack to avoid capturing `this` in the dispatch_async
255+
id<MTRCommissionableBrowserDelegate> delegate = mDelegate;
256+
MTRDeviceController * controller = mController;
257+
VerifyOrReturn(delegate != nil && controller != nil);
251258

252259
MATTER_LOG_METRIC(kMetricOnNetworkDevicesRemoved, ++mOnNetworkDevicesRemoved);
253260

@@ -278,7 +285,7 @@ void OnBrowseRemove(DnssdService service) override
278285
// resolving it), so don't bother notifying about the removal either.
279286
if (result.instanceName != nil) {
280287
dispatch_async(mDispatchQueue, ^{
281-
[mDelegate controller:mController didRemoveCommissionableDevice:result];
288+
[delegate controller:controller didRemoveCommissionableDevice:result];
282289
});
283290
}
284291

@@ -298,7 +305,11 @@ void OnBrowseStop(CHIP_ERROR error) override
298305
void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificationInfo & info) override
299306
{
300307
assertChipStackLockedByCurrentThread();
301-
VerifyOrReturn(mDelegate != nil);
308+
309+
// Copy delegate and controller to the stack to avoid capturing `this` in the dispatch_async
310+
id<MTRCommissionableBrowserDelegate> delegate = mDelegate;
311+
MTRDeviceController * controller = mController;
312+
VerifyOrReturn(delegate != nil && controller != nil);
302313

303314
auto result = [[MTRCommissionableBrowserResult alloc] init];
304315
result.instanceName = [NSString stringWithUTF8String:kBleKey];
@@ -315,14 +326,18 @@ void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificati
315326
mDiscoveredResults[key] = result;
316327

317328
dispatch_async(mDispatchQueue, ^{
318-
[mDelegate controller:mController didFindCommissionableDevice:result];
329+
[delegate controller:controller didFindCommissionableDevice:result];
319330
});
320331
}
321332

322333
void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override
323334
{
324335
assertChipStackLockedByCurrentThread();
325-
VerifyOrReturn(mDelegate != nil);
336+
337+
// Copy delegate and controller to the stack to avoid capturing `this` in the dispatch_async
338+
id<MTRCommissionableBrowserDelegate> delegate = mDelegate;
339+
MTRDeviceController * controller = mController;
340+
VerifyOrReturn(delegate != nil && controller != nil);
326341

327342
auto key = [NSString stringWithFormat:@"%@", connObj];
328343
if ([mDiscoveredResults objectForKey:key] == nil) {
@@ -336,12 +351,13 @@ void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override
336351
MATTER_LOG_METRIC(kMetricBLEDevicesRemoved, ++mBLEDevicesRemoved);
337352

338353
dispatch_async(mDispatchQueue, ^{
339-
[mDelegate controller:mController didRemoveCommissionableDevice:result];
354+
[delegate controller:controller didRemoveCommissionableDevice:result];
340355
});
341356
}
342357

343358
void OnBleScanStopped() override
344359
{
360+
assertChipStackLockedByCurrentThread();
345361
mBleScannerDelegateOwner = nil;
346362
}
347363

@@ -350,22 +366,21 @@ void OnBleScanStopped() override
350366
private:
351367
dispatch_queue_t mDispatchQueue;
352368
id<MTRCommissionableBrowserDelegate> mDelegate;
353-
MTRDeviceController * mController;
369+
MTRDeviceController * __weak mController;
354370
NSMutableDictionary<NSString *, MTRCommissionableBrowserResult *> * mDiscoveredResults;
355371
int32_t mOnNetworkDevicesAdded;
356372
int32_t mOnNetworkDevicesRemoved;
357373
int32_t mBLEDevicesAdded;
358374
int32_t mBLEDevicesRemoved;
359375
};
360376

361-
@interface MTRCommissionableBrowser ()
362-
@property (strong, nonatomic) dispatch_queue_t queue;
363-
@property (nonatomic, readonly) id<MTRCommissionableBrowserDelegate> delegate;
364-
@property (nonatomic, readonly) MTRDeviceController * controller;
365-
@property (unsafe_unretained, nonatomic) CommissionableBrowserInternal browser;
366-
@end
377+
@implementation MTRCommissionableBrowser {
378+
id<MTRCommissionableBrowserDelegate> _delegate;
379+
dispatch_queue_t _queue;
380+
MTRDeviceController * __weak _controller;
381+
CommissionableBrowserInternal _browser;
382+
}
367383

368-
@implementation MTRCommissionableBrowser
369384
- (instancetype)initWithDelegate:(id<MTRCommissionableBrowserDelegate>)delegate
370385
controller:(MTRDeviceController *)controller
371386
queue:(dispatch_queue_t)queue

0 commit comments

Comments
 (0)