Skip to content

Menu bar: poll stats continuously from launch (real fix for stuck spinner)#84

Open
iliyami wants to merge 1 commit into
mainfrom
fix/menu-stats-continuous-polling
Open

Menu bar: poll stats continuously from launch (real fix for stuck spinner)#84
iliyami wants to merge 1 commit into
mainfrom
fix/menu-stats-continuous-polling

Conversation

@iliyami

@iliyami iliyami commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Follow-up to #78/#79. A reporter confirmed the menu-bar "Live system stats" popover still stuck on its loading spinner on the 1.11.5 beta, which already had the statfs + timeout fix. So that fix targeted the wrong layer.

Real root cause

Polling was started only from the MenuBarExtra(.window) popover content's .onAppear and stopped on .onDisappear. That hook only fires when the popover opens, and is unreliable across macOS versions, so on the reporter's Mac collection never ran and stats stayed nil → permanent spinner. Changing what collect() does internally (the 1.11.5 fix) couldn't help if polling never starts.

Evidence: a sample of his helper showed it alive but completely idle (no collection threads); locally, wrapping the helper in a .app and launching it produced no stats activity until the popover was opened.

Fix

Move polling into a @MainActor @Observable MenuStatsModel started at launch from MenuAppDelegate.applicationDidFinishLaunching (@NSApplicationDelegateAdaptor), decoupled from the popover lifecycle:

  • Stats collected from launch → popover shows data instantly; the menu-bar label is populated immediately (previously blank until first open).
  • @MainActor model → UI updates on the main actor.
  • Per-metric withTimeout retained; timeouts log at .error so a remaining slow syscall (if any) is pinpointable from Console.

Verified locally: launching the bundled helper runs collection and sets stats within ~2s without opening the popover (confirmed via a file-write probe; note os_log .info is not retrievable via log show, so don't rely on it).

Notes

  • @preconcurrency NSApplicationDelegate conformance to keep CI's older SDK building.
  • Version bumped to 1.11.6 (1.11.5 shipped only as betas).
  • I'll cut v1.11.6-beta.1 for the reporter to confirm; if it still spins, the .error "exceeded its budget" log will identify a per-syscall stall.

The live-stats popover stayed stuck on its loading spinner for a reporter even
on the 1.11.5 beta (which already had the statfs/timeout fix). The cause was not
the disk read: polling was started ONLY from the MenuBarExtra(.window) popover
content's .onAppear and torn down on .onDisappear. That hook only fires when the
popover opens and is unreliable across macOS versions, so collection often never
ran and stats stayed nil.

Move polling into a @mainactor @observable MenuStatsModel started at launch from
the app delegate (applicationDidFinishLaunching), decoupled from the popover:

- Stats are gathered from launch, so the popover shows data instantly and the
  menu-bar label is populated immediately (previously blank until first open).
- @mainactor model means UI updates happen on the main actor.
- Per-metric withTimeout retained so one slow syscall degrades to last-known
  instead of blanking the panel; timeouts log at .error for field diagnosis.

Verified locally: launching the bundled helper runs collection and populates
stats within ~2s without ever opening the popover.

Bump version to 1.11.6.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant