Pewarta Proxy

📋 Server Request & Proxy Logs

Loading active proxy settings...
Developed by Khairul Adha (adhexa.id)
Mengambil log server...

⚙️ Pengaturan Proxy Target

Skip to content

Recurring multi-hour VM hangs on arm64: do_seccomp → kick_all_cpus_sync IPI never returns, RCU sched starves, vmgr pinned at ~200% CPU #2471

Closed

Description

@alex-fedotyev

Recurring multi-hour VM hangs on arm64: do_seccomp → kick_all_cpus_sync IPI never returns, RCU sched starves, vmgr pinned at ~200% CPU

Describe the bug

The OrbStack guest Linux VM enters a partial-freeze state from which it never self-recovers. Once it happens, orb status reports Starting and the docker socket is unresponsive — but the helper process (vmgr) is alive and consuming ~200% CPU indefinitely. The only recovery is killing OrbStack and restarting it. This has happened multiple times per day for the past few weeks.

The OrbStack watchdog autonomously samples the process when this state is detected and writes ~/.orbstack/log/vmgr.sample.log — that file (and the kernel printk traces in vmgr.log) point to the same root cause every time: the guest kernel's BPF JIT compiler is installed by a seccomp filter, the JIT issues a cross-CPU IPI via __text_poke → kick_all_cpus_sync, and the IPI never completes. smp_call_function_many_cond spins forever, the RCU grace-period kthread (rcu_sched) starves, and everything downstream stalls. The host vmgr keeps spinning trying to drive the wedged guest.

Canonical guest-kernel stack (identical across 189 separate captures in a single session)

do_seccomp.cold+135
  __arm64_sys_seccomp+35
  → bpf_prog_create_from_user.cold+219
    → bpf_prepare_filter+775
      → bpf_prog_select_runtime+83
        → bpf_int_jit_compile+1247
          → bpf_jit_binary_pack_finalize+39
            → bpf_arch_text_copy+27
              → aarch64_insn_copy+55
                → __text_poke+251
                  → kick_all_cpus_sync+71
                    → smp_call_function_many_cond+916    ← spins here, never returns

The same vCPU (in our case vCPU 9) is always the victim. RCU stall traces are emitted continuously, e.g.:

rcu: rcu_sched kthread starved for 98415 jiffies! g448205 f0x0 RCU_GP_WAIT_FQS(5) ->state=0x402 ->cpu=9
rcu: Unless rcu_sched kthread gets sufficient CPU time, OOM is now expected behavior.

The starvation counter climbs continuously (98k → 7.3M jiffies over 2 hours in today's incident). At one point OrbStack's VirtualClock thread rebases the guest clock — the jiffy counter rolls back partway, then the same vCPU re-wedges on the same BPF JIT path within seconds. The hypervisor's recovery attempt does not break the deadlock.

Downstream cascade once vCPU is dead

  • brnet::bridge::macos: failed to write packet to guest [BufferFull] — thousands of dropped packets to the guest (2,789 in 2h).
  • vmgr: failed to send fsnotify events ... endpoint is closed for send — the host→guest fsnotify TCP channel (control port) tears down (8,337 errors in 2h). After this, file-change notifications to bind mounts are dead even if some IO still moves.
  • docker CLI commands hang indefinitely. orb status returns Starting (exit 2) although the VM has been booted for hours.
  • vmgr (OrbStack Helper vmgr) is permanently at 199% CPU (2 cores pinned) and grows its physical footprint to >20 GB.

To Reproduce

Exact deterministic reproduction has not been isolated, but the trigger profile is consistent:

  1. Apple Silicon Mac, macOS 26.5, OrbStack 2.1.3.
  2. Allocate OrbStack the default resources (no custom CPU/memory cap).
  3. Bring up multiple Docker Compose projects simultaneously — in our case 3 separate compose stacks at boot, each containing a long-running database service plus several application containers (~15–20 containers total across all stacks).
  4. Let the VM run for several hours while containers perform routine work (no churn required, no rebuilds, no docker pull). Periodic health-check execs and any new container starts trigger fresh seccomp BPF JIT compiles.
  5. Some time between 3 and 4 hours after VM boot, the RCU stall fires and the VM never recovers. In today's incident, VM was booted at 07:49 and the first rcu_sched starvation message appeared at 11:24 (printk timestamp ~12,724 s after boot). The watchdog logged its first stacks sampled at 11:51:40.

Frequency: 1–3 times per day in our environment. Always the same guest-kernel call path.

Expected behavior

Either:

  • The BPF JIT path should not deadlock on kick_all_cpus_sync — i.e. the cross-CPU IPI broadcast should always complete (this is a guest-kernel / hypervisor-IPI-delivery interaction issue specific to OrbStack's Hypervisor.framework / Virtualization-based vCPU scheduling on aarch64); or
  • If the IPI is genuinely lost, the hypervisor should be able to break the deadlock without an external restart, and orb status / docker should not block on it.

Diagnostic report (REQUIRED)

Not attached. When OrbStack enters this state, the daemon is wedged: orb feedback panics with timed out waiting for services to start and orb report cannot complete. Generating a fresh orb report would require killing OrbStack and starting a new VM, which would destroy the in-memory state of the actual incident.

The OrbStack watchdog has, however, already auto-captured a 165 KB stack-sample log of every host-side vmgr thread at the time of detection. The relevant excerpts are inline above. I'm happy to upload the full vmgr.sample.log and a filtered vmgr.log (RCU stall traces + BPF JIT stack samples only) privately if useful — please advise how to share these; we are willing to share them only with OrbStack staff via a private channel since they contain hypervisor symbol offsets and some host process metadata.

If desired I can run orb report after recovering from the next hang (will be a "post-recovery" report on a clean VM, not the wedged state).

Additional context

Host environment

Field Value
OrbStack 2.1.3 (build 2010300), commit 7a3258b7336a8a47b75771e87ef7b74ba4bba8eb
macOS 26.5 (build 25F71)
Chip Apple Silicon, arm64, 14 cores
Host RAM 36 GB
Host swap at hang time 4.45 / 5.12 GB used (~87%), ~6 k free pages
OrbStack VM physical footprint at hang 21.0 GB (peak 23.8 GB)
OrbStack ~/.orbstack/config/docker.json empty {} (defaults only)

The host swap saturation is a consequence of the hang (vmgr's footprint grows while spinning), not the trigger — the first RCU stall fires before host swap is full. We also see prior occurrences in rotated logs where the host had abundant free memory at the time of the stall.

Recurrence evidence

  • ~/.orbstack/log/vmgr.log (current session): 189 distinct stack samples, all on the same do_seccomp → kick_all_cpus_sync path; 27 distinct rcu_sched kthread starved printk progress messages.
  • ~/.orbstack/log/vmgr.1.log (rotated, prior session): also contains a stacks sampled watchdog event minutes before rotation — confirms this is not a one-off and recurs across reboots.

Workload profile (sanitized)

The workload is a small set of docker-compose projects running a long-running columnar database service alongside several supporting service containers. Container churn is low (no rebuilds, no docker run loops) — only routine compose up at the start of the day plus container health-check execs. Crucially, no --privileged, no VPN/gluetun, no unusual ulimit nofile, no oversized bind-mount sets. The compose stacks use plain bridge networking and named volumes.

This means the trigger is not "heavy I/O", not "too many interfaces", not "container thrash" — it's specifically that the kernel's seccomp BPF JIT path on arm64 occasionally loses an IPI ack and deadlocks.

Suspected upstream area

This call path — bpf_jit_binary_pack_finalize → bpf_arch_text_copy → aarch64_insn_copy → __text_poke → kick_all_cpus_sync — is what aarch64 added in Linux ~6.x to flush I-caches after JITting executable BPF text into the BPF JIT region. On bare metal this is unconditionally safe; under a virtualized arm64 environment where IPI delivery depends on the hypervisor scheduling target vCPU threads in time, a missed IPI can leave the caller blocked on smp_call_function_many_cond forever.

I suspect either:

  • a subtle race between vCPU thread preemption on the host and IPI completion, where the target vCPU is descheduled before it can ack; or
  • a Hypervisor.framework / Virtualization.framework issue where an IPI raised while a vCPU is in WFE/WFI is occasionally not delivered when the vCPU wakes.

Either way, it's reachable from inside a normal container starting up — which means any user who starts enough containers will eventually hit it.

Workaround attempted

Adding security_opt: ["seccomp=unconfined"] to compose services prevents the kernel from installing a BPF program for seccomp, which avoids the BPF JIT path entirely. This is what we are using locally to keep dev environments usable, but it's not acceptable as a long-term fix.

What would help us help you

  1. A way to selectively disable BPF JIT (e.g. net.core.bpf_jit_enable=0) inside the OrbStack docker VM as a documented mitigation.
  2. Confirmation whether a kernel patch for kick_all_cpus_sync aarch64 robustness is on the roadmap, or whether this needs to go upstream first.
  3. Whether a host-side workaround (different IPI delivery / different vCPU pinning strategy) is being considered for 2.x.

Happy to test patched builds, run with extra instrumentation, or attach more logs.

Activity

  1. kdrag0n commented on May 21, 2026

    @kdrag0n
    Member

    Please attach orb report after restarting OrbStack. This analysis is inaccurate and doesn't have enough info for debugging.

  2. alex-fedotyev commented on May 22, 2026

    @alex-fedotyev
    Author

    Additional info from a fresh occurrence today (2026-05-22):

    Diagnostic bundle

    orb report (taken after restart, as requested): attaching orbstack-diagreport.zip in a follow-up (docker-compose project names redacted; nothing else altered).

    OrbStack info:

    • Version: 2.1.3
    • Commit: 7a3258b7336a8a47b75771e87ef7b74ba4bba8eb (v2.1.3)
    • macOS: 26.5 (25F71) on Apple M4 Max, 14 cores, 36 GiB

    Captured stuck state (before restart)

    OrbStack's own hang detector fired and auto-sampled stacks — 40 separate "sampling stacks due to VM hang" events between 14:40:36 and 15:24:52 (~45 min sustained wedged state, not transient). Every event shows the same kernel stack on every vCPU:

    smp_call_function_many_cond     ← waiting on IPI rendezvous
    kick_all_cpus_sync
    __text_poke                     ← patching kernel text
    aarch64_insn_copy
    bpf_arch_text_copy
    bpf_jit_binary_pack_finalize
    bpf_int_jit_compile             ← compiling a BPF program
    bpf_prog_select_runtime
    bpf_prepare_filter
    bpf_prog_create_from_user.cold
    do_seccomp.cold                 ← from a seccomp() syscall
    __arm64_sys_seccomp
    

    Classic deadlock pattern: a guest userspace process called seccomp(), the kernel started JIT-compiling its BPF filter, which needs an all-CPU IPI to patch kernel text — but every vCPU is itself stuck inside smp_call_function_many_cond waiting on that same IPI. Nothing makes progress.

    Host-side fallout was consistent with the guest being wedged: failed to send fsnotify events: endpoint is closed for send, host-tcp forward: context deadline exceeded, brnet::bridge::macos: failed to write packet to guest error=BufferFull, health check failed: Post "http://vcontrol/disk/report_stats": context deadline exceeded.

    Process state right before restart:

    • OrbStack Helper vmgr running since May 18, ~22 GB RSS, pinned at ~298% CPU, ~969 min CPU time accumulated.

    Attaching vm-hang-first-event.log (single representative hang event — vCPU register dumps + stacks) in the follow-up. The full OrbStack-captured sample is included in the diag bundle as vmgr_logs/vmgr.sample.log.

    Restart behavior

    Quitting OrbStack typically hangs in this state — the GUI app can't respond to the Quit Apple Event because vmgr is wedged. kill -TERM on the helper also doesn't work; kill -KILL on the OrbStack Helper vmgr PID is required. After force-kill, relaunch is clean (vmgr healthy in ~2s).

    Trigger speculation

    Common to the workloads I run are docker-compose stacks with multiple containers that apply seccomp profiles on startup (default docker behavior). The hang seems to develop over multi-day uptime — this VM had been up since May 18.

  3. alex-fedotyev commented on May 22, 2026

    @alex-fedotyev
    Author
  4. alex-fedotyev commented on May 22, 2026

    @alex-fedotyev
    Author

    @kdrag0n - hope this help, appreciate your help here, it is a very annoying issue

  5. kdrag0n commented on May 22, 2026

    @kdrag0n
    Member

    Already fixed for the next version.

  6. added this to the v2.1.4 milestone on May 22, 2026
  7. kdrag0n commented on Jun 4, 2026

    @kdrag0n
    Member

    Released in v2.2.0.

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

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions