Skip to content

macOS: sfw-free proxy can busy-loop at ~80% CPU and never exit after mid-request network interruption; copies accumulate #51

Description

@amotivv

Summary

On macOS, after a mid-request network interruption, sfw-free proxy processes can get stuck in a persistent CPU spin and never exit. I observed 17 accumulated proxy processes at ~80% CPU each after overnight sleep/wake cycles. I could not reproduce the spin on Linux, which points toward a possible macOS/kqueue-specific event-loop issue.

I did a fair amount of digging (details + measurements below) and it looks like a libuv event-loop spin on a dead/half-closed socket that is specific to macOS (kqueue) I could not reproduce it on Linux. I have not been able to pin the exact line.

Possibly related: #38 (runaway processes when npm/npx are globally wrapped) and #25 (signal/lifecycle handling).

Environment

  • macOS (Apple Silicon, arm64)
  • sfw (npm wrapper) v2.0.6
  • sfw-free binary v1.10.0 at the time of the incident; I separately confirmed the cited source is unchanged through v1.12.0 (current latest), so it still applies
  • npm/npx globally wrapped via a PATH shim, so every package-manager call routes through sfw (same setup as Runaway process loop when npm/npx are globally wrapped by sfw on Ubuntu (Remote SSH / agent workflow) #38)
  • Trigger: a background process that ran npm view <pkg>@latest version --prefer-online repeatedly (≈ hourly in this incident), across overnight sleep/wake cycles

Symptoms (observed)

17 sfw-free proxy processes (the Node SEA that spawns the package manager) alive simultaneously. Activity Monitor showed all 17 at 79.6–82.0% CPU; a few rows (instantaneous %CPU and accumulated CPU time):

%CPU   CPU TIME    PROCESS
82.0   17:07.89    sfw-free-macos-arm64
81.7   12:48.21    sfw-free-macos-arm64
81.2   25:18.32    sfw-free-macos-arm64
…      (17 rows total)

ps confirmed all 17 were state R (on-CPU), on the same TTY, ~250 MB RSS, each running:

sfw-free-macos-arm64 npm view <pkg>@latest version --prefer-online
  • Start times were spread ~1/hour across ~19 hours (12:44 PM → 8:05 AM the next day), matching the update-check interval plus overnight sleep/wake.
  • At that moment the machine was at 97% user / 0% idle.
  • The same command run fresh completes in ~2.7s, so this is a state-dependent hang.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions