Observed once during PiP verification on #7798 (build a6badf5, tag pip) under extreme host load (loadavg 70-160, ~78 users, dozens of agents): after an ~18s CLI timeout on a stateful verb, every MainActor-bound socket verb (tree, identify, rename-tab, surface pip) timed out for 15+ minutes while ping kept answering and terminals kept rendering (Metal threads). sample shows the main thread pinned for the whole window inside NSHostingView.layout → ViewGraph.renderDisplayList → DisplayList.ViewUpdater.Container.removeRemaining(viewCache:) → CoreViewLayerView → objc_loadWeak → weak_entry_for_referent (21/22 samples in the objc weak-table walk). No cmux frames below the hosting view — this is the SwiftUI huge-view-cache teardown family (cf. #2586). Sample: /tmp/fable-feat-surface-pip/evidence-3/10-sample-during-hang.txt, log: 10a-socket-wedge.txt (machine-local).
Downstream effect: SIGTERM during the stall cannot write the quit-time session snapshot, so relaunch restores the last periodic snapshot; in the observed case that resurrected panes/surfaces closed long before quit (looked like "phantom panes with fresh shells"). A clean pop→SIGTERM→relaunch at normal conditions round-trips correctly, so the restore path itself is sound.
Two directions worth separating: (1) whatever makes removeRemaining walk an enormous weak table on one display-cycle flush; (2) socket-side, consider a watchdog that fails stateful verbs fast with a distinct main_thread_stalled error instead of generic client timeouts, so callers and quit paths can distinguish a stall from slowness.
Observed once during PiP verification on #7798 (build a6badf5, tag pip) under extreme host load (loadavg 70-160, ~78 users, dozens of agents): after an ~18s CLI timeout on a stateful verb, every MainActor-bound socket verb (tree, identify, rename-tab, surface pip) timed out for 15+ minutes while
pingkept answering and terminals kept rendering (Metal threads).sampleshows the main thread pinned for the whole window inside NSHostingView.layout → ViewGraph.renderDisplayList → DisplayList.ViewUpdater.Container.removeRemaining(viewCache:) → CoreViewLayerView → objc_loadWeak → weak_entry_for_referent (21/22 samples in the objc weak-table walk). No cmux frames below the hosting view — this is the SwiftUI huge-view-cache teardown family (cf. #2586). Sample: /tmp/fable-feat-surface-pip/evidence-3/10-sample-during-hang.txt, log: 10a-socket-wedge.txt (machine-local).Downstream effect: SIGTERM during the stall cannot write the quit-time session snapshot, so relaunch restores the last periodic snapshot; in the observed case that resurrected panes/surfaces closed long before quit (looked like "phantom panes with fresh shells"). A clean pop→SIGTERM→relaunch at normal conditions round-trips correctly, so the restore path itself is sound.
Two directions worth separating: (1) whatever makes removeRemaining walk an enormous weak table on one display-cycle flush; (2) socket-side, consider a watchdog that fails stateful verbs fast with a distinct
main_thread_stallederror instead of generic client timeouts, so callers and quit paths can distinguish a stall from slowness.