garrytan / garrytan/gstack

Windows on ARM64 (Snapdragon): ./setup intermittently deadlocks in fork-heavy bash loops (gstack-patch-names / link_codex_skill_dirs) under x64-emulated Git-Bash

Open
#2,120 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
133k
Forks
19.9k
Avg merge
18h 46m
Merged PRs (30d)
26

Description

## Summary

On Windows 11 on ARM64 (Snapdragon X Elite), `./setup` intermittently **deadlocks** partway through and hangs indefinitely. I traced it to fork-heavy bash loops (`bin/gstack-patch-names`, and — after I patched that one — `link_codex_skill_dirs` in `setup`) wedging in MSYS2's `fork()` emulation, which here is executed by an **x86-64 Git-Bash running under Windows-on-ARM x64 emulation**.

## Environment

- Windows 11 ARM64, Qualcomm Snapdragon X Elite
- gstack **v1.58.5.0**, global git install (`~/.claude/skills/gstack`), host = claude (+ codex detected)
- Git for Windows is **hybrid**: native ARM64 git (`file $(which git)` → `ARM64`) but **x86-64 bash** (`file $(which bash)` → `PE32+ … x86-64`) → the shell runs under Prism x64 emulation
- bun (x64), node (x64 via fnm)

## Symptom

`./setup` prints through skill-doc generation, then hangs with **no further output and no `bun`/`node` process alive**. `bash -x ./setup` shows the last executed command is the `bin/gstack-patch-names 0` invocation. Tracing `gstack-patch-names` itself shows it wedged mid-loop on a per-file `grep -m1 '^name:' … | sed … | tr …` pipeline. The exact file **varies between runs** (non-deterministic), and that pipeline runs fine **in isolation** — it only deadlocks inside the bulk loop. It's intermittent: the daily auto-upgrade has completed cleanly on quiet days and hung during active use.

## Root cause

`gstack-patch-names` spawns `grep | sed | tr` (3 procs) + `basename` per skill — roughly **4 forks × ~55 skills ≈ 220** rapid `fork()`/`CreateProcess` calls. MSYS2's `fork()` is fragile by nature; under x64-on-ARM64 emulation (and amplified by AV scanning each spawned child) it intermittently deadlocks. Rewriting `gstack-patch-names` to be **fork-free** (read the frontmatter `name:` with a bash builtin `read` loop — ~2s, zero forks) fixed that step, but `./setup` then hung at the **next** fork-heavy loop, `link_codex_skill_dirs`. So it's systemic to the fork-per-file pattern, not a single script.

## Minimal repro (on an affected machine)

```bash
# Intermittently deadlocks (often within a few runs) on x64-emulated MSYS2 bash:
time bash ~/.claude/skills/gstack/bin/gstack-patch-names ~/.claude/skills/gstack 0
```

(Note it's a no-op for already-unprefixed installs — `PATCHED=0` — yet still hangs, because every iteration forks `grep|sed|tr` just to *read* the name.)

## Suggested fix

Replace the per-file process pipelines in the setup loops with a single-pass / fork-free approach:

- **`gstack-patch-names`**: read the frontmatter `name:` with a bash `read` loop (no fork) and only spawn `sed`/`mv` when an actual rename is required (usually none). Or do the whole job in one `awk`/`bun` pass over all `SKILL.md` files.
- Apply the same to `link_codex_skill_dirs` / `link_claude_skill_dirs` (avoid `basename` + `grep`/`sed` per iteration).

This removes the fork storm that triggers the deadlock and also speeds setup up on every platform. I have a verified fork-free `gstack-patch-names` drop-in and am happy to open a PR if useful.

Contributor guide

Open the contributing guide

Research direction

Start with ./setup, bin/gstack-patch-names, and the link_codex_skill_dirs and link_claude_skill_dirs loops; reproduce the hang with the provided time bash command on affected Git-Bash. Trace the per-file process pipelines and compare the suggested fork-free approach. Done means setup completes reliably without fork-heavy per-file loops while preserving name patching and skill linking.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.