Skip to content

fix: prevent Maintenance Sleep to keep WebSocket bridge alive#512

Merged
PureWeen merged 2 commits intomainfrom
shneuvil/relaunch-lock-screen
Apr 5, 2026
Merged

fix: prevent Maintenance Sleep to keep WebSocket bridge alive#512
PureWeen merged 2 commits intomainfrom
shneuvil/relaunch-lock-screen

Conversation

@PureWeen
Copy link
Copy Markdown
Owner

@PureWeen PureWeen commented Apr 5, 2026

Summary

  • Upgrades NSActivityOptions in AppDelegate.cs from 0x00FFFFFF to 0xFF00FFFFFF by adding NSActivityLatencyCritical (0xFF00000000)
  • NSActivityUserInitiated alone does not prevent Maintenance Sleep — macOS can still enter deep idle and suspend network I/O
  • With NSActivityLatencyCritical, Maintenance Sleep is blocked entirely, keeping WsBridgeServer reachable while the Mac is locked or idle

Problem

Mobile clients were seeing "connection refused" for 5–10 minute windows. Diagnosed via pmset -g log: Mac entered Maintenance Sleep at 13:16:02 (triggered by a Spotlight indexing job), DarkWake at 13:31:39 — 15 minutes of network suspension with no app-level indication.

Test plan

  • Lock the Mac for 15+ minutes while a mobile client is connected via direct network share
  • Verify the WebSocket bridge remains reachable throughout (no connection refused)
  • Confirm pmset -g log shows no Maintenance Sleep entries while the activity is held

🤖 Generated with Claude Code

macOS can enter Maintenance Sleep even when NSActivityUserInitiated
(0x00FFFFFF) is held, suspending network I/O and causing mobile clients
to see connection refused for 5-10 minute windows.

Adding NSActivityLatencyCritical (0xFF00000000) to the activity options
prevents Maintenance Sleep and all deep-idle states, keeping WsBridgeServer
reachable at all times.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@PureWeen
Copy link
Copy Markdown
Owner Author

PureWeen commented Apr 5, 2026

🔍 Multi-Model Code Review — PR #512

fix: prevent Maintenance Sleep to keep WebSocket bridge alive

CI Status

⚠️ No CI checks reported on this branch


Findings

🟡 MODERATE — Magic number cast when named enum members exist (2/3 reviewers)

File: PolyPilot/Platforms/MacCatalyst/AppDelegate.csFinishedLaunching, line 25

The comment states these flags are "not in .NET Catalyst bindings" — this is incorrect. Reflection of the installed Microsoft.MacCatalyst.dll (net10.0_26.2 ref pack) confirms all three values exist:

NSActivityOptions (underlying: UInt64)
  UserInitiated    = 0x00FFFFFF
  LatencyCritical  = 0xFF00000000
  UserInteractive  = 0xFF00FFFFFF  ← exact match for the magic number

The raw hex cast (NSActivityOptions)0xFF00FFFFFF is functionally equivalent to the already-available NSActivityOptions.UserInteractive. The false comment will mislead future maintainers.

Suggested fix: Replace (NSActivityOptions)0xFF00FFFFFF with NSActivityOptions.UserInitiated | NSActivityOptions.LatencyCritical (or NSActivityOptions.UserInteractive), and remove the "not in .NET Catalyst bindings" claim.


Discarded Findings (adversarial round)

LatencyCritical scoped to full app lifetime (1/3 reviewers → 0/3 after adversarial): One reviewer suggested scoping LatencyCritical to active WebSocket client connections rather than holding it for the app's full lifetime. The other two reviewers independently rejected this — the bridge server must accept incoming connections at any time, so releasing the flag when no clients are connected creates a chicken-and-egg problem: the Mac enters Maintenance Sleep, the TCP listener freezes, and new connections fail. For a persistent server app, lifetime-scoped activity is correct.


Verified Correct ✅

  • Bitmask arithmetic: 0x00FFFFFF | 0xFF00000000 = 0xFF00FFFFFF — matches Apple's NSProcessInfo.h header
  • Type safety: NSActivityOptions is UInt64-backed; the value fits with no truncation
  • Lifecycle: BeginActivity in FinishedLaunching, EndActivity in WillTerminate — properly paired, both on main thread, no race
  • OS compatibility: NSActivityLatencyCritical has no API_AVAILABLE gate in the Apple header — raw bits work on all supported macOS versions

Test Coverage

No new tests needed — this is a platform configuration change (single constant), not a logic change. The test plan in the PR description (manual lock-screen verification + pmset -g log) is appropriate.


Re-Review (after fix commit)

Previous Finding Status

# Finding Status
1 🟡 Magic number cast / false "not in bindings" comment FIXED — Replaced (NSActivityOptions)0xFF00FFFFFF with NSActivityOptions.UserInitiated | NSActivityOptions.LatencyCritical. False comment removed. Flag descriptions now accurate.

Re-Review Results

All 3 reviewers confirmed the fix is clean:

  • Named enum members used correctly (UserInitiated \| LatencyCritical)
  • Behavioral delta is precisely and only the addition of LatencyCritical — no unintended flags introduced
  • _activityToken cleanup in WillTerminate is correct and unchanged

Updated Recommendation

Approve — the single finding is fully addressed. Clean, correct, well-commented change.

Replace `(NSActivityOptions)0xFF00FFFFFF` with the explicit OR of the
two named constants — `UserInitiated | LatencyCritical` — which are
available in the .NET Catalyst bindings. Also removes the incorrect
comment claiming the flags are absent from the bindings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@PureWeen
Copy link
Copy Markdown
Owner Author

PureWeen commented Apr 5, 2026

Fixed — replaced the magic number cast with NSActivityOptions.UserInitiated | NSActivityOptions.LatencyCritical and removed the incorrect "not in .NET Catalyst bindings" comment. (03da467)

@PureWeen PureWeen merged commit d82efe8 into main Apr 5, 2026
@PureWeen PureWeen deleted the shneuvil/relaunch-lock-screen branch April 5, 2026 23:18
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