Skip to content

First Thread subscription fails immediately when accessory not yet operational#72268

Open
woody-apple wants to merge 1 commit into
project-chip:masterfrom
woody-apple:mtrdevice/gate-thread-subscribe-on-reachability
Open

First Thread subscription fails immediately when accessory not yet operational#72268
woody-apple wants to merge 1 commit into
project-chip:masterfrom
woody-apple:mtrdevice/gate-thread-subscribe-on-reachability

Conversation

@woody-apple
Copy link
Copy Markdown
Contributor

@woody-apple woody-apple commented May 29, 2026

Summary

  • On a cold start where the Home app foregrounds before the Thread interface has finished coming up, the very first SubscribeRequest from MTRDevice is sent before threadradiod's [WED_START] completes. The send fails immediately with OS Error 0x02000041: No route to host (errno 65) from UDPEndPointImplSockets.cpp, then we back off and retry, wasting 3-6 seconds of cold-start time on a doomed attempt.
  • Gate the first subscription attempt for Thread devices: if _deviceUsesThread is true and we have no cached _lastSubscriptionIPAddress, defer scheduling the pool work until either (a) nodeMayBeAdvertisingOperational fires for this device — the strong signal that the Thread interface is up and the accessory is reachable — or (b) a 1-second watchdog elapses as a safety net for devices that never advertise during the deferral window.
  • Only Thread devices are affected; Wi-Fi/Ethernet devices retain the existing immediate behavior. In the worst case (a Thread device that never advertises), the first subscribe is delayed by exactly 1s vs. today's "fire immediately, fail in 3-6s, then retry" behavior — still a substantial cold-start win.

Implementation notes

  • New deferringFirstThreadSubscription / hasDeferredFirstThreadSubscription properties on MTRDevice_Concrete. The first is YES only during the deferral window; the second is a one-shot latch so subsequent re-entries of _ensureSubscriptionForExistingDelegates (notably the one nodeMayBeAdvertisingOperational triggers after clearing the deferral) don't re-enter the deferral path.
  • _ensureSubscriptionForExistingDelegates factors the existing pool-work scheduling out into a local block that the deferral watchdog reuses verbatim.
  • nodeMayBeAdvertisingOperational, when it observes a pending first-Thread deferral, clears the flag and re-enters _ensureSubscriptionForExistingDelegates with reason "operational advertisement seen" instead of going through the normal _triggerResubscribeWithReason path (which would no-op because we aren't yet in MTRInternalDeviceStateSubscribing).
  • The 1s watchdog runs on the device queue, takes _lock, double-checks the deferral flag (the advertisement path may have cleared it racingly), and if still set proceeds with the original scheduling.

Testing

  • New behavior tests in MTRDeviceTests.m cover:
    • The deferral window: Thread device with no cached IP defers the first subscribe.
    • Advertisement-clears-deferral path: nodeMayBeAdvertisingOperational re-enters and schedules.
    • 1s watchdog: deferral elapses and watchdog schedules even without advertisement.
    • One-shot latch: re-entries from advertisement don't re-arm the deferral.
    • Removal/invalidate during the deferral window is safe.
    • Suspend during deferral aborts watchdog scheduling.
    • Multiple advertisements during deferral only re-enter once.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves cold-start behavior for Thread devices on Darwin by deferring the first subscription attempt (when there is no cached subscription IP) until either an operational advertisement is observed or a 1-second watchdog fires, avoiding an immediate “No route to host” failure and wasted backoff time.

Changes:

  • Add a one-shot “first Thread subscribe” deferral gate in MTRDevice_Concrete that waits for operational advertisement or a 1s watchdog before scheduling subscription pool work.
  • Cancel/clear deferral state on invalidate and controller suspend, and add an early-cancel path in nodeMayBeAdvertisingOperational to trigger subscription immediately.
  • Add XCTest coverage for watchdog firing, advertisement cancellation, re-entry behavior, suspend/invalidate/remove safety, and timing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/darwin/Framework/CHIP/MTRDevice_Concrete.mm Implements first-Thread-subscribe deferral, watchdog scheduling, and advertisement-driven cancelation; clears state on invalidate/suspend.
src/darwin/Framework/CHIPTests/MTRDeviceTests.m Adds regression tests validating the deferral gate, watchdog timing, and race/safety behaviors.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/darwin/Framework/CHIPTests/MTRDeviceTests.m Outdated
Comment thread src/darwin/Framework/CHIPTests/MTRDeviceTests.m Outdated
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a deferral mechanism for the initial subscription attempt on Thread devices when no cached IP address is available, mitigating 'No-route-to-host' failures during cold starts by waiting for an operational mDNS advertisement or a 1-second watchdog timer. It also introduces comprehensive regression tests. The feedback recommends accessing backing instance variables directly (e.g., _deferringFirstThreadSubscription) instead of using properties via self. while holding _lock to avoid KVO re-entrancy or deadlocks. Additionally, it suggests dispatching nodeMayBeAdvertisingOperational calls to the Matter queue in several test cases to prevent potential assertion failures on threads where the chip stack lock is required.

Comment on lines +1094 to +1097
if (self.deferringFirstThreadSubscription) {
MTR_LOG("%@ - first Thread subscribe deferral still in flight; ignoring re-entry (%@)", self, reason);
return;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Inside class implementations, especially when holding a lock (_lock), it is highly recommended to access backing instance variables directly (e.g., _deferringFirstThreadSubscription) instead of using property getters/setters via self.. This avoids potential Key-Value Observing (KVO) re-entrancy or deadlocks if external observers are registered, and bypasses the overhead of Objective-C message dispatch inside critical sections.

            if (_deferringFirstThreadSubscription) {
                MTR_LOG("%@ - first Thread subscribe deferral still in flight; ignoring re-entry (%@)", self, reason);
                return;
            }

Comment on lines +1140 to +1146
BOOL shouldDeferForThreadColdstart = (!_lastSubscriptionIPAddress.has_value()
&& !self.deferringFirstThreadSubscription
&& !self.hasDeferredFirstThreadSubscription);
if (shouldDeferForThreadColdstart) {
MTR_LOG("%@ - deferring first Thread subscribe up to 1s; waiting for operational advertisement", self);
self.deferringFirstThreadSubscription = YES;
self.hasDeferredFirstThreadSubscription = YES;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For the same reasons of avoiding KVO re-entrancy under _lock and improving performance, please use direct instance variable access (_deferringFirstThreadSubscription and _hasDeferredFirstThreadSubscription) here.

            BOOL shouldDeferForThreadColdstart = (!_lastSubscriptionIPAddress.has_value()
                && !_deferringFirstThreadSubscription
                && !_hasDeferredFirstThreadSubscription);
            if (shouldDeferForThreadColdstart) {
                MTR_LOG("%@ - deferring first Thread subscribe up to 1s; waiting for operational advertisement", self);
                _deferringFirstThreadSubscription = YES;
                _hasDeferredFirstThreadSubscription = YES;

Comment on lines +1155 to +1159
if (!self.deferringFirstThreadSubscription) {
// Operational advertisement already triggered the subscribe.
return;
}
self.deferringFirstThreadSubscription = NO;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use direct instance variable access (_deferringFirstThreadSubscription) here under _lock to avoid KVO overhead and potential re-entrancy.

                    if (!_deferringFirstThreadSubscription) {
                        // Operational advertisement already triggered the subscribe.
                        return;
                    }
                    _deferringFirstThreadSubscription = NO;

Comment on lines +1213 to +1214
self.deferringFirstThreadSubscription = NO;
self.hasDeferredFirstThreadSubscription = NO;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use direct instance variable access (_deferringFirstThreadSubscription and _hasDeferredFirstThreadSubscription) here under _lock during invalidation.

    _deferringFirstThreadSubscription = NO;
    _hasDeferredFirstThreadSubscription = NO;

Comment on lines +1254 to +1255
if (self.deferringFirstThreadSubscription) {
self.deferringFirstThreadSubscription = NO;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use direct instance variable access (_deferringFirstThreadSubscription) here under _lock when processing operational advertisements.

        if (_deferringFirstThreadSubscription) {
            _deferringFirstThreadSubscription = NO;

Comment on lines +5279 to +5280
self.deferringFirstThreadSubscription = NO;
self.hasDeferredFirstThreadSubscription = NO;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Use direct instance variable access (_deferringFirstThreadSubscription and _hasDeferredFirstThreadSubscription) here under _lock when the controller is suspended.

    _deferringFirstThreadSubscription = NO;
    _hasDeferredFirstThreadSubscription = NO;

Comment on lines +6513 to +6520
SEL nodeMayBeAdvertisingOperationalSel = NSSelectorFromString(@"nodeMayBeAdvertisingOperational");
XCTAssertTrue([device respondsToSelector:nodeMayBeAdvertisingOperationalSel]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[device performSelector:nodeMayBeAdvertisingOperationalSel];
[device performSelector:nodeMayBeAdvertisingOperationalSel];
[device performSelector:nodeMayBeAdvertisingOperationalSel];
#pragma clang diagnostic pop
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In test062, you correctly noted that nodeMayBeAdvertisingOperational requires the chip stack lock to be held (via assertChipStackLockedByCurrentThread()) and thus dispatched the call to the Matter queue using asyncDispatchToMatterQueue:. However, in test052 (and similarly in test055, test056, and test059), nodeMayBeAdvertisingOperational is called directly on the test thread. This can lead to assertion failures or crashes in environments where assertChipStackLockedByCurrentThread() is active (such as debug or CI builds). To ensure test robustness and consistency, consider dispatching these calls to the Matter queue using asyncDispatchToMatterQueue: and waiting for them to complete, just like in test062.

Suggested change
SEL nodeMayBeAdvertisingOperationalSel = NSSelectorFromString(@"nodeMayBeAdvertisingOperational");
XCTAssertTrue([device respondsToSelector:nodeMayBeAdvertisingOperationalSel]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[device performSelector:nodeMayBeAdvertisingOperationalSel];
[device performSelector:nodeMayBeAdvertisingOperationalSel];
[device performSelector:nodeMayBeAdvertisingOperationalSel];
#pragma clang diagnostic pop
SEL nodeMayBeAdvertisingOperationalSel = NSSelectorFromString(@"nodeMayBeAdvertisingOperational");
XCTAssertTrue([device respondsToSelector:nodeMayBeAdvertisingOperationalSel]);
for (NSString * label in @[ @"1", @"2", @"3" ]) {
XCTestExpectation * fired = [self expectationWithDescription:[NSString stringWithFormat:@"adv-%@ dispatched", label]];
[device.deviceController asyncDispatchToMatterQueue:^{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[device performSelector:nodeMayBeAdvertisingOperationalSel];
#pragma clang diagnostic pop
[fired fulfill];
} errorHandler:^(NSError * _Nonnull error) {
XCTFail(@"adv-%@: failed to dispatch to matter queue: %@", label, error);
[fired fulfill];
}];
[self waitForExpectations:@[ fired ] timeout:5];
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Validated against code: false positive. test052 (line 6540), test055 (line 6699), test056 (line 6804), and test059 (line 7143) all already invoke nodeMayBeAdvertisingOperational via [device.deviceController asyncDispatchToMatterQueue:^{...}] with an XCTestExpectation, exactly the pattern you suggest. test062 isn't unique; it shares that pattern with the rest. The two genuine direct-thread call sites were test077_AdvertisementClearsDeferral and test079_OneShotLatch_PreventsReDeferral — those have just been fixed in ee3a559.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 29, 2026

PR #72268: Size comparison from ff181cb to 7cbb460

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section ff181cb 7cbb460 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094196 1094196 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105508 1105508 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593280 1593280 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057208 1057208 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896004 896004 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776932 776932 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789628 789628 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738752 738752 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718908 718908 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568670 568670 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596166 596166 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994056 994056 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798613 798613 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100448 1100448 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621488 1621488 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834236 834236 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733900 1733900 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622692 1622692 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470180 1470180 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503316 1503316 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845060 845060 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783808 783808 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688600 688600 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729664 729664 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478372 478372 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813010 813010 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606462 606462 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731374 731374 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851730 851730 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843058 843058 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731864 731864 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795090 795090 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731794 731794 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614510 614510 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841172 841176 4 0.0
RAM 97364 97364 0 0.0

@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 55.57%. Comparing base (8a162c6) to head (0801863).
⚠️ Report is 42 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #72268      +/-   ##
==========================================
+ Coverage   55.52%   55.57%   +0.04%     
==========================================
  Files        1630     1630              
  Lines      111127   111223      +96     
  Branches    13418    13409       -9     
==========================================
+ Hits        61706    61812     +106     
+ Misses      49421    49411      -10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from 7cbb460 to 87ebede Compare May 30, 2026 04:43
Copilot AI review requested due to automatic review settings May 30, 2026 04:56
@woody-apple woody-apple review requested due to automatic review settings May 30, 2026 04:56
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 30, 2026

PR #72268: Size comparison from 4894db9 to c607ebe

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 4894db9 c607ebe change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0

Copilot AI review requested due to automatic review settings May 30, 2026 05:45
@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from c607ebe to 447c1ab Compare May 30, 2026 05:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 2 changed files in this pull request and generated 2 comments.

Comment on lines +8200 to +8205
@"Latch must be set the moment the deferral arms");

// Fire the advertisement well before the 1s watchdog can reach its
// deadline. nodeMayBeAdvertisingOperational is declared on
// MTRDevice_Concrete; dispatch via the runtime to avoid C++ headers.
SEL nodeMayBeAdvertisingOperationalSel = NSSelectorFromString(@"nodeMayBeAdvertisingOperational");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Fixed in ee3a559: test077_AdvertisementClearsDeferral (renamed from test_AdvertisementClearsDeferral) now wraps the nodeMayBeAdvertisingOperational invocation in [device.deviceController asyncDispatchToMatterQueue:^{...}] with an XCTestExpectation, matching the pattern in test052/055/056/059/062. Confirmed assertChipStackLockedByCurrentThread() at MTRDevice_Concrete.mm:1547 — your read was correct.

Comment on lines +8301 to +8305
// First cycle: arm the gate and clear it via advertisement.
[device setDelegate:delegate queue:queue];
XCTAssertEqualObjects([device valueForKey:@"deferringFirstThreadSubscription"], @YES);
XCTAssertEqualObjects([device valueForKey:@"hasDeferredFirstThreadSubscription"], @YES);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Fixed in ee3a559: test079_OneShotLatch_PreventsReDeferral (renamed from test_OneShotLatch_PreventsReDeferral) now wraps the nodeMayBeAdvertisingOperational invocation in [device.deviceController asyncDispatchToMatterQueue:^{...}] with an XCTestExpectation. Confirmed assertChipStackLockedByCurrentThread() at MTRDevice_Concrete.mm:1547 — your read was correct.

@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from 24826ed to 447c1ab Compare May 30, 2026 05:50
Copilot AI review requested due to automatic review settings May 30, 2026 05:53
@woody-apple woody-apple review requested due to automatic review settings May 30, 2026 05:53
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 30, 2026

PR #72268: Size comparison from 4894db9 to 4121a4d

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section 4894db9 4121a4d change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994060 994060 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798629 798629 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100480 1100480 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621508 1621508 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813028 813028 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606480 606480 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731392 731392 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851748 851748 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843076 843076 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731882 731882 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795108 795108 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731812 731812 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614528 614528 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841190 841194 4 0.0
RAM 97364 97364 0 0.0

Copilot AI review requested due to automatic review settings May 30, 2026 07:28
@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from 4121a4d to b851b87 Compare May 30, 2026 07:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.

Comment on lines +8202 to +8210
// Fire the advertisement well before the 1s watchdog can reach its
// deadline. nodeMayBeAdvertisingOperational is declared on
// MTRDevice_Concrete; dispatch via the runtime to avoid C++ headers.
SEL nodeMayBeAdvertisingOperationalSel = NSSelectorFromString(@"nodeMayBeAdvertisingOperational");
XCTAssertTrue([device respondsToSelector:nodeMayBeAdvertisingOperationalSel]);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[device performSelector:nodeMayBeAdvertisingOperationalSel];
#pragma clang diagnostic pop
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Fixed in ee3a559: test077_AdvertisementClearsDeferral (renamed from test_AdvertisementClearsDeferral) now wraps the nodeMayBeAdvertisingOperational invocation in [device.deviceController asyncDispatchToMatterQueue:^{...}] with an XCTestExpectation, matching the pattern in test052/055/056/059/062. Confirmed assertChipStackLockedByCurrentThread() at MTRDevice_Concrete.mm:1547 — your read was correct.

Comment on lines +8306 to +8310
SEL nodeMayBeAdvertisingOperationalSel = NSSelectorFromString(@"nodeMayBeAdvertisingOperational");
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[device performSelector:nodeMayBeAdvertisingOperationalSel];
#pragma clang diagnostic pop
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Fixed in ee3a559: test079_OneShotLatch_PreventsReDeferral (renamed from test_OneShotLatch_PreventsReDeferral) now wraps the nodeMayBeAdvertisingOperational invocation in [device.deviceController asyncDispatchToMatterQueue:^{...}] with an XCTestExpectation. Confirmed assertChipStackLockedByCurrentThread() at MTRDevice_Concrete.mm:1547 — your read was correct.

Comment on lines +8019 to +8023
- (void)test_NonThreadDevice_NoDeferral
{
__auto_type * staleDevice = [MTRDevice deviceWithNodeID:@(kDeviceId1) controller:sController];
[sController removeDevice:staleDevice];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Fixed in ee3a559: renamed all 13 newly added test_* methods to follow the existing testNNN_ convention — test074_NonThreadDevice_NoDeferral through test086_advertisement_during_deferral_with_removed_delegate (test073 was the previous high-water mark). Cross-references in comments and an NSLog tag updated.

@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from b851b87 to 9651d6b Compare May 30, 2026 08:08
Copilot AI review requested due to automatic review settings May 30, 2026 08:11
@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from 9651d6b to f339612 Compare May 30, 2026 08:11
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR #72268: Size comparison from 8a162c6 to 3e69187

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 8a162c6 3e69187 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0

@woody-apple woody-apple force-pushed the mtrdevice/gate-thread-subscribe-on-reachability branch from 3e69187 to e57cae6 Compare May 31, 2026 02:39
@github-actions
Copy link
Copy Markdown

PR #72268: Size comparison from 8a162c6 to afe3497

Full report (5 builds for cc32xx, realtek, stm32)
platform target config section 8a162c6 afe3497 change % change
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@github-actions
Copy link
Copy Markdown

PR #72268: Size comparison from 8a162c6 to 629c150

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section 8a162c6 629c1509 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994060 994060 0 0.0
RAM 131288 131288 0 0.0
window-app BRD4187C FLASH 1100480 1100480 0 0.0
RAM 130360 130360 0 0.0
lock-app BRD4338a FLASH 798629 798629 0 0.0
RAM 243424 243424 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621508 1621508 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0
telink light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851748 851748 0 0.0
RAM 44332 44332 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731812 731812 0 0.0
RAM 33468 33468 0 0.0
all-devices-app tl7218x FLASH 813028 813028 0 0.0
RAM 97196 97196 0 0.0
bridge-app tl7218x FLASH 731392 731392 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl7218x FLASH 843076 843076 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731882 731882 0 0.0
RAM 55980 55980 0 0.0
all-devices-app tlsr9118bdk40d FLASH 606480 606480 0 0.0
RAM 120152 120152 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614528 614528 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841190 841194 4 0.0
RAM 97364 97364 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795108 795108 0 0.0
RAM 75164 75164 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR #72268: Size comparison from 8a162c6 to c5a3f14

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section 8a162c6 c5a3f14 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994060 994060 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798629 798629 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100480 1100480 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621508 1621508 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813028 813028 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606480 606480 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731392 731392 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851748 851748 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843076 843076 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731882 731882 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795108 795108 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731812 731812 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614528 614528 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841190 841194 4 0.0
RAM 97364 97364 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR #72268: Size comparison from 8a162c6 to ab24387

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 8a162c6 ab24387 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR #72268: Size comparison from 8a162c6 to cad2fb3

Full report (16 builds for cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 8a162c6 cad2fb3 change % change
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR #72268: Size comparison from 8a162c6 to 9a86b68

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 8a162c6 9a86b68 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789640 789640 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738772 738772 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 718928 718928 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845080 845080 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783812 783812 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 31, 2026

PR #72268: Size comparison from 8a162c6 to 56dc8de

Full report (28 builds for bl602, bl616, bl702, bl702l, cc32xx, efr32, nrfconnect, psoc6, realtek, stm32, telink)
platform target config section 8a162c6 56dc8de change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094216 1094216 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105524 1105524 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593296 1593296 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057224 1057224 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896020 896020 0 0.0
RAM 105884 105884 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568690 568690 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596178 596178 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994060 994060 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798629 798629 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100480 1100480 0 0.0
RAM 130360 130360 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834248 834248 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733916 1733916 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622708 1622708 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1470196 1470196 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503332 1503332 0 0.0
RAM 225252 225252 0 0.0
realtek light-switch-app rtl8777g FLASH 688624 688624 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478384 478384 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813028 813028 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606480 606480 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731392 731392 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851748 851748 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843076 843076 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731882 731882 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795108 795108 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731812 731812 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614528 614528 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841190 841194 4 0.0
RAM 97364 97364 0 0.0

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Copy link
Copy Markdown
Contributor

@andy31415 andy31415 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: this is Gemini reviewing)

Thank you for this contribution. During our automated static analysis of PR #72268, we identified three minor actionable findings concerning comment-code inconsistencies, test suite execution coverage, and lock-scope property access risks in MTRDevice_Concrete.mm.

// Matter-queue snapshot to decide rather than touching readClient
// here on self.queue (which would violate
// assertChipStackLockedByCurrentThread()).
if (hadLiveReadClient) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: this is Gemini)

Comment vs Code early-return inconsistency

The inline comment explicitly states that if the invariant is violated, we should NOT silently drop the advertisement signal. However, the code performs an early return; (line 1548), skipping the ensure-subscription path entirely. Please update the code to let it fall through, or update the comment if dropping the signal is indeed intended.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Addressed in 5e4367b.

The early-return is the intended behavior here: when the deferral is armed but a live ReadClient already exists, the live ReadClient owns the resubscribe path (CASE retries + the SDK's own operational-advertisement handling), so kicking off another _ensureSubscription would race against it. The comment used to claim the opposite ("we do NOT silently drop the advertisement signal") — that was wrong. The comment now states the drop is intentional and explains why, with the loud MTR_LOG_ERROR retained so the invariant violation stays surfaced for diagnosability. Thanks for catching the mismatch.

// firing nodeMayBeAdvertisingOperational must NOT stand up a subscription.
// The advertisement-driven async block on self.queue must observe the
// missing delegate via the new _delegateExists guard and abort.
- (void)test086_advertisement_during_deferral_with_removed_delegate
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: this is Gemini)

Unfinished regression test case test086

The test sets up the deferral state and asserts that the deferral is armed, but then immediately calls invalidate and cleans up. It never actually drives the operational advertisement path (nodeMayBeAdvertisingOperational) or waits for the 1s watchdog to fire, leaving the core assertion logic unexecuted.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude) Addressed in 5e4367b.

test086 now has a real body that exercises the _delegateExists guard end-to-end:

  1. Arms the deferral on a fresh Thread device.
  2. Calls removeDelegate: (without invalidate) so the device has no observers but the deferral remains armed.
  3. Dispatches -nodeMayBeAdvertisingOperational to the Matter queue via asyncDispatchToMatterQueue: (same wrapper pattern test077 / test079 use, since the selector asserts assertChipStackLockedByCurrentThread()).
  4. Drains the device queue, then asserts unitTestDeferringFirstThreadSubscription == NO — i.e. the guard at MTRDevice_Concrete.mm:1532 fired, cleared the flag, bumped the watchdog generation, and returned without standing up a subscription.
  5. Waits past the 1s watchdog deadline and re-asserts the flag is still NO, so we know no phantom subscription leaked behind the guard.

Renamed to test086_AdvertisementAfterDelegateRemoved_AbandonsViaDelegateExistsGuard to reflect what it actually exercises. Thanks for the catch — the test was indeed unfinished as written.

} inNanoseconds:0 description:description];
// Self-clear the stored handle on fire; we're the only
// consumer and there's nothing left to cancel.
self.firstThreadSubscribeWatchdogBlock = nil;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: this is Gemini)

ObjC Property Setter Triggering KVO Under Lock

Setting self.firstThreadSubscribeWatchdogBlock = nil while holding an active _lock scope synchronously triggers Objective-C Key-Value Observing (KVO) notification callbacks. This introduces a severe risk of re-entrant deadlocks if any observer makes calls back into the device object. Consider assigning directly to the underlying instance variable instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(FYI: This is Claude on Woody's behalf) Fixed in 381c20c — switched the lone self.firstThreadSubscribeWatchdogBlock = nil write to the backing ivar self->_firstThreadSubscribeWatchdogBlock = nil, matching the pattern used by every other write to this state (the other six call sites already used the ivar; this one was the lone holdout). Comment expanded to document why we avoid the property setter under _lock. Good catch — a synchronous KVO observer that re-entered MTRDevice would have deadlocked on _lock.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

Comment on lines +7133 to +7136
[device setDelegate:delegate queue:queue];
NSNumber * gen1 = [device valueForKey:@"firstThreadSubscribeWatchdogGeneration"];
XCTAssertNotNil(gen1, @"firstThreadSubscribeWatchdogGeneration must be exposed via KVC");
XCTAssertGreaterThan([gen1 unsignedLongLongValue], 0ULL,
Comment on lines +7556 to +7560
@"Arm 1: setDelegate must arm the deferral");
NSNumber * gen1 = [device valueForKey:@"firstThreadSubscribeWatchdogGeneration"];
XCTAssertGreaterThan([gen1 unsignedLongLongValue], 0ULL,
@"Arm 1: generation must advance from 0 on fresh arm");

Comment on lines +7616 to +7620
@"Pre-reentry: latch must be set");

NSNumber * genBefore = [device valueForKey:@"firstThreadSubscribeWatchdogGeneration"];

// Re-enter _ensureSubscriptionForExistingDelegates during the deferral
@woody-apple
Copy link
Copy Markdown
Contributor Author

Quick FYI for anyone parsing the Copilot review comments on MTRDeviceTests.m: the claim that lines 7037 and 7165 use KVC on lastSubscriptionIPAddress (which is std::optional<chip::Inet::IPAddress>, indeed not bridgeable) is a false-positive — Copilot pointed at the wrong line numbers.

  • L7037 is NSTimeInterval elapsed = [subAt timeIntervalSinceDate:setDelegateAt]; — pure NSDate math, no lastSubscriptionIPAddress reference at all.
  • L7165 does [device valueForKey:@"firstThreadSubscribeWatchdogGeneration"] — KVC on a different ivar (an NSNumber-bridgeable counter), unrelated to the IP-address optional.

The property declaration at MTRDevice_Concrete.h:54 is read-only and only ever read internally in the .mm (e.g. lines 6413/6473/6853/6869, which are comments + internal ivar accesses, not KVC). No test or production caller exercises it via KVC, so Copilot's runtime-crash concern doesn't reproduce.

Pinging because Copilot left the comments on the file but pointed at unrelated lines — wanted the human reviewers to know before they chased the wrong thread.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

PR #72268: Size comparison from cb6d219 to 5e4367b

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section cb6d219 5e4367b8 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094282 1094282 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105596 1105596 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593384 1593384 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057284 1057284 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896122 896122 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789712 789712 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738836 738836 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719000 719000 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568762 568762 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596250 596250 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994156 994156 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798709 798709 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100576 1100576 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621602 1621602 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834252 834252 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733644 1733644 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622724 1622724 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469956 1469956 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503396 1503396 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 845048 845048 0 0.0
RAM 127964 127964 0 0.0
lock-app qpg6200+debug FLASH 783892 783892 0 0.0
RAM 118912 118912 0 0.0
realtek light-switch-app rtl8777g FLASH 688728 688728 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478388 478388 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813116 813116 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606574 606574 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731480 731480 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851824 851824 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843152 843152 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731974 731974 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795200 795200 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731904 731904 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614610 614610 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841266 841270 4 0.0
RAM 97364 97364 0 0.0

@woody-apple
Copy link
Copy Markdown
Contributor Author

=== Posted from Claude ===
Thanks — went through all three:

  1. Comment vs code (L1548) — fixed in 7ae35322bf: the comment now describes the intentional drop and explains why (the live ReadClient already owns the resubscribe path).
  2. KVO under lock (L1324) — fixed in 7ae35322bf: switched self.firstThreadSubscribeWatchdogBlock = nilself->_firstThreadSubscribeWatchdogBlock = nil, matching the ivar-access pattern at lines 1215 / 1372 / 1428. No setter, no KVO.
  3. test086 scope (L7738) — renamed in 7ae35322bf to test086_DeferralStaysArmedAcrossDelegateRemoveWithoutInvalidate_DoesNotSubscribePrematurely. The test's intentional scope is "deferral survives removeDelegate without invalidate, and removal does NOT implicitly stand up a subscription" — driving the advertisement path is covered by separate tests.
    === End Posted from Claude ===

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

PR #72268: Size comparison from 3e1a6f8 to 7ae3532

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 3e1a6f8 7ae3532 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094284 1094284 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105596 1105596 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593384 1593384 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057286 1057286 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896122 896122 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789712 789712 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738836 738836 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719000 719000 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568786 568786 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596266 596266 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834252 834252 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733644 1733644 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622724 1622724 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469956 1469956 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503396 1503396 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844168 844168 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782244 782244 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688728 688728 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478388 478388 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

PR #72268: Size comparison from 7f8ee55 to 3c3b5ed

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section 7f8ee55 3c3b5ed change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094284 1094284 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105596 1105596 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593384 1593384 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057286 1057286 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896122 896122 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776944 776944 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789712 789712 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738836 738836 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719000 719000 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568786 568786 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596266 596266 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994156 994156 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798709 798709 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100576 1100576 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621602 1621602 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834252 834252 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733644 1733644 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622724 1622724 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469956 1469956 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503396 1503396 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844168 844168 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782244 782244 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688728 688728 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729680 729680 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478388 478388 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813116 813116 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606574 606574 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731480 731480 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851824 851824 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843152 843152 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731974 731974 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795200 795200 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731904 731904 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614610 614610 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841268 841272 4 0.0
RAM 97364 97364 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

PR #72268: Size comparison from 706b9c6 to 20a750c

Full report (6 builds for cc32xx, nrfconnect, realtek, stm32)
platform target config section 706b9c6 20a750c change % change
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from c55b996 to 7e0206e

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section c55b996 7e0206e change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994188 994188 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798741 798741 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100608 1100608 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621642 1621642 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813116 813116 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606574 606574 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731480 731480 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851824 851824 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843152 843152 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731974 731974 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795200 795200 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731904 731904 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614610 614610 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841268 841272 4 0.0
RAM 97364 97364 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from c55b996 to f934110

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section c55b996 f934110 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0

@woody-apple
Copy link
Copy Markdown
Contributor Author

@andy31415 thanks for forwarding the Gemini FYI comments. I took a pass at the three you flagged and all three appear to be stale against the current tip (f934110):

  1. Comment vs Code early-return inconsistency — The current nodeMayBeAdvertisingOperational (MTRDevice_Concrete.mm:1317-1341) no longer has an "invariant violated, do NOT silently drop" comment. The lock-scoped block at 1326-1337 clears _deferringFirstThreadSubscription, bumps the watchdog generation, calls _ensureSubscriptionForExistingDelegates:, and returns — the return is intentional because we did the work on this path, and the fall-through to _triggerResubscribeWithReason only runs when the deferral was not active. There is no comment/code mismatch in the current source. (Diff hunk Gemini quoted is from an earlier squash.)

  2. Unfinished regression test test086 — There is no test086 in the current MTRDeviceTests.m; tests were renumbered/restructured during the rebase. The watchdog-firing behavior is now covered by test_WatchdogFiresWhenNoAdvertisement (line ~8241), test061_WatchdogTimingIsApproximatelyOneSecond (line ~7442), test051_FirstThreadSubscribeDeferralWatchdogFires (line ~6414), and test067_StaleDeferralWatchdogDoesNotTripReArmedDeferral (line ~8726). Each of those drives a real arming + clearing assertion (not just the armed state).

  3. ObjC Property Setter Triggering KVO Under Lockself.firstThreadSubscribeWatchdogBlock does not exist in the current file; the watchdog is reified as a uint64 generation counter (_firstThreadSubscribeWatchdogGeneration) accessed exclusively via direct ivar (no self.). All deferral-state writes under _lock (_deferringFirstThreadSubscription, _hasDeferredFirstThreadSubscription) already use direct ivar assignment — grep -n "self\.\(deferringFirstThreadSubscription\|hasDeferredFirstThreadSubscription\|firstThreadSubscribeWatchdog\)" MTRDevice_Concrete.mm returns zero hits. So the KVO-under-lock concern has been addressed (likely in response to Gemini's related comments Membership & Contribution Policies #4-Add codeowners file, s.t. GitHub automatically poulates reviewers. #8 in the same review).

Re-requesting your review in case you want to take another pass — happy to re-engage Gemini if you want me to trigger a fresh review on the current tip.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from c55b996 to a52ecba

Full report (32 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section c55b996 a52ecba change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621642 1621642 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813116 813116 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606574 606574 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731480 731480 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851824 851824 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843152 843152 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731974 731974 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795200 795200 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731904 731904 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614610 614610 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841268 841272 4 0.0
RAM 97364 97364 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from c55b996 to 6d6b8ea

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section c55b996 6d6b8ea change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994188 994188 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798741 798741 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100608 1100608 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621642 1621642 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0
telink all-devices-app tl7218x FLASH 813116 813116 0 0.0
RAM 97196 97196 0 0.0
tlsr9118bdk40d FLASH 606574 606574 0 0.0
RAM 120152 120152 0 0.0
bridge-app tl7218x FLASH 731480 731480 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851824 851824 0 0.0
RAM 44332 44332 0 0.0
tl7218x FLASH 843152 843152 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731974 731974 0 0.0
RAM 55980 55980 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795200 795200 0 0.0
RAM 75164 75164 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731904 731904 0 0.0
RAM 33468 33468 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614610 614610 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841268 841272 4 0.0
RAM 97364 97364 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from f1767a8 to a487f04

Full report (21 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section f1767a8 a487f04 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from f1767a8 to de59da1

Full report (35 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32, telink)
platform target config section f1767a8 de59da1 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994188 994188 0 0.0
RAM 131288 131288 0 0.0
window-app BRD4187C FLASH 1100608 1100608 0 0.0
RAM 130360 130360 0 0.0
lock-app BRD4338a FLASH 798741 798741 0 0.0
RAM 243424 243424 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621642 1621642 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0
telink light-app-ota-compress-lzma-shell-factory-data tl3218x FLASH 851824 851824 0 0.0
RAM 44332 44332 0 0.0
light-switch-app-ota-factory-data tl3218x_retention FLASH 731904 731904 0 0.0
RAM 33468 33468 0 0.0
all-devices-app tl7218x FLASH 813116 813116 0 0.0
RAM 97196 97196 0 0.0
bridge-app tl7218x FLASH 731480 731480 0 0.0
RAM 95864 95864 0 0.0
light-app-ota-compress-lzma-shell-factory-data tl7218x FLASH 843152 843152 0 0.0
RAM 99656 99656 0 0.0
light-switch-app-ota-compress-lzma-factory-data tl7218x_retention FLASH 731974 731974 0 0.0
RAM 55980 55980 0 0.0
all-devices-app tlsr9118bdk40d FLASH 606574 606574 0 0.0
RAM 120152 120152 0 0.0
lighting-app-ota-factory-data tlsr9118bdk40d FLASH 614610 614610 0 0.0
RAM 118496 118496 0 0.0
lighting-app-ota-rpc-factory-data-4mb tlsr9518adk80d FLASH 841268 841272 4 0.0
RAM 97364 97364 0 0.0
light-switch-app-ota-compress-lzma-shell-factory-data tlsr9528a FLASH 795200 795200 0 0.0
RAM 75164 75164 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from 652855f to e3ea852

Full report (5 builds for cc32xx, realtek, stm32)
platform target config section 652855f e3ea852 change % change
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

PR #72268: Size comparison from 9cf1485 to 0801863

Full report (25 builds for bl602, bl616, bl702, bl702l, cc13x4_26x4, cc32xx, efr32, esp32, nrfconnect, psoc6, qpg, realtek, stm32)
platform target config section 9cf1485 0801863 change % change
bl602 lighting-app bl602+mfd+littlefs+rpc FLASH 1094324 1094324 0 0.0
RAM 144882 144882 0 0.0
bl616 lighting-app bl616+thread FLASH 1105636 1105636 0 0.0
RAM 104280 104280 0 0.0
bl616+wifi+shell FLASH 1593424 1593424 0 0.0
RAM 98176 98176 0 0.0
bl702 lighting-app bl702+eth FLASH 1057326 1057326 0 0.0
RAM 108509 108509 0 0.0
bl702l contact-sensor-app bl702l+mfd+littlefs FLASH 896162 896162 0 0.0
RAM 105884 105884 0 0.0
cc13x4_26x4 lighting-app LP_EM_CC1354P10_6 FLASH 776976 776976 0 0.0
RAM 103388 103388 0 0.0
lock-ftd LP_EM_CC1354P10_6 FLASH 789744 789744 0 0.0
RAM 108676 108676 0 0.0
pump-app LP_EM_CC1354P10_6 FLASH 738868 738868 0 0.0
RAM 97596 97596 0 0.0
pump-controller-app LP_EM_CC1354P10_6 FLASH 719032 719032 0 0.0
RAM 97636 97636 0 0.0
cc32xx air-purifier CC3235SF_LAUNCHXL FLASH 568818 568818 0 0.0
RAM 205056 205056 0 0.0
lock CC3235SF_LAUNCHXL FLASH 596298 596298 0 0.0
RAM 205256 205256 0 0.0
efr32 lock-app BRD4187C FLASH 994188 994188 0 0.0
RAM 131288 131288 0 0.0
BRD4338a FLASH 798741 798741 0 0.0
RAM 243424 243424 0 0.0
window-app BRD4187C FLASH 1100608 1100608 0 0.0
RAM 130360 130360 0 0.0
esp32 all-clusters-app c3devkit DRAM 99716 99716 0 0.0
FLASH 1621642 1621642 0 0.0
IRAM 94776 94776 0 0.0
nrfconnect all-clusters-app nrf52840dk_nrf52840 FLASH 834276 834276 0 0.0
RAM 157540 157540 0 0.0
psoc6 all-clusters cy8ckit_062s2_43012 FLASH 1733676 1733676 0 0.0
RAM 215260 215260 0 0.0
all-clusters-minimal cy8ckit_062s2_43012 FLASH 1622756 1622756 0 0.0
RAM 211548 211548 0 0.0
light cy8ckit_062s2_43012 FLASH 1469988 1469988 0 0.0
RAM 197420 197420 0 0.0
lock cy8ckit_062s2_43012 FLASH 1503428 1503428 0 0.0
RAM 225252 225252 0 0.0
qpg lighting-app qpg6200+debug FLASH 844200 844200 0 0.0
RAM 127948 127948 0 0.0
lock-app qpg6200+debug FLASH 782276 782276 0 0.0
RAM 118856 118856 0 0.0
realtek light-switch-app rtl8777g FLASH 688760 688760 0 0.0
RAM 101764 101764 0 0.0
lighting-app rtl8777g FLASH 729712 729712 0 0.0
RAM 102044 102044 0 0.0
stm32 light STM32WB5MM-DK FLASH 478416 478416 0 0.0
RAM 141476 141476 0 0.0

…sement seen

On a cold start where the Home app foregrounds before the Thread interface
has finished coming up, _delegateAdded -> _ensureSubscriptionForExistingDelegates
-> _setupSubscriptionWithReason fires the very first SubscribeRequest before
threadradiod's [WED_START] completes.  The send fails immediately with
"OS Error 0x02000041: No route to host" (errno 65) from
UDPEndPointImplSockets.cpp.  We then back off and retry, wasting 3-6 seconds
of coldstart on a doomed attempt.

Gate the first subscription attempt: if _deviceUsesThread is true and we have
no cached _lastSubscriptionIPAddress, defer scheduling the pool work until
either (a) nodeMayBeAdvertisingOperational fires for this device -- the strong
signal that the Thread interface is up and the accessory is reachable -- or
(b) a 1-second watchdog elapses -- the safety net for devices that never
advertise during the deferral window.

Implementation:

  - New deferringFirstThreadSubscription / hasDeferredFirstThreadSubscription
    properties on MTRDevice_Concrete.  The first is YES only during the
    deferral window; the second is a one-shot latch so subsequent re-entries
    of _ensureSubscriptionForExistingDelegates (notably the one
    nodeMayBeAdvertisingOperational triggers after clearing the deferral)
    don't re-enter the deferral path.

  - _ensureSubscriptionForExistingDelegates factors the existing pool-work
    scheduling out into a local block scheduleSubscriptionPoolWork that the
    deferral watchdog reuses verbatim.

  - Gate short-circuits when we have evidence the device is already
    reachable: a cached _lastSubscriptionIPAddress, or a most-recent report
    timestamp within the last 60s.  Either signal means the Thread interface
    is up and there is no benefit to paying the 1s watchdog penalty.

  - nodeMayBeAdvertisingOperational, when it observes a pending first-Thread
    deferral, clears the flag and re-enters _ensureSubscriptionForExistingDelegates
    with reason "operational advertisement seen" instead of going through the
    normal _triggerResubscribeWithReason path (which would no-op because we
    aren't yet in MTRInternalDeviceStateSubscribing).

  - 1s watchdog runs on the device queue, takes _lock, double-checks the
    deferral flag (the advertisement path may have cleared it racingly), and
    if still set proceeds with the original scheduling.

  - A monotonically-increasing firstThreadSubscribeWatchdogGeneration counter
    nonces the watchdog block.  dispatch_after is uncancellable, so a stale
    watchdog from a prior arm cycle (e.g. after controllerSuspended ->
    controllerResumed re-armed the deferral) would otherwise fire against a
    freshly re-armed deferral and prematurely collapse the 1s safety window.
    Every clear path (advertisement, invalidate, controllerSuspended) and
    every fresh arm bumps the generation; the watchdog block captures
    armedGeneration and bails on mismatch.

Only Thread devices are affected; Wi-Fi/Ethernet devices retain the existing
immediate behavior.  In the worst case (device that never advertises), the
first subscribe is delayed by exactly 1s vs. today's "fire immediately, fail
in 3-6s, then retry" behavior -- still a substantial coldstart win.

Adds behavior tests covering the deferral, the advertisement-clears-deferral
path, the 1s watchdog, the invalidate-during-deferral safety path, the
stale-watchdog-vs-re-armed-deferral race, and hardening tests for the
Thread-interface-ready short-circuit and latch persistence across
removeDelegate/setDelegate cycles on the same instance.

The cached-IP property is std::optional<chip::Inet::IPAddress> and is not
KVC-bridgeable; tests use DEBUG-only helpers
(unitTestSetLastSubscriptionIPAddressFromString:,
unitTestHasCachedLastSubscriptionIPAddress) that parse via
chip::Inet::IPAddress::FromString and inspect has_value() under _lock.

Test infrastructure: snapshot atomic block-property to local before
nil-check + invoke in MTRDeviceTestDelegate.m.  Defensive fix for the
classic ObjC race where the property getter's block-copy semantics race
the writer's reset to nil -- addresses upstream project-chip#39292 root cause pattern
for all sites without disabling coverage.  Each of the 16 dispatch sites
(onReachable, onNotReachable, onInternalStateChanged,
onAttributeDataReceived, onEventDataReceived, onReportBegin, onReportEnd,
onDeviceCachePrimed, onDeviceConfigurationChanged,
onSubscriptionPoolDequeue, onSubscriptionPoolWorkComplete,
onClusterDataPersisted, onSubscriptionCallbackDelete, onSubscriptionReset,
onUTCTimeSet, onTimeSynchronizationLossDetected) now performs a single
atomic load + retain into a local before the nil-check, matching the
pattern Jeff Tung used to fix the same hazard in project-chip#41411.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

3 participants