Skip to content

fix: prevent readStdin() from hanging indefinitely on Windows#74

Open
myselfsiddharth wants to merge 1 commit into
supermemoryai:mainfrom
myselfsiddharth:fix/windows-stdin-hang
Open

fix: prevent readStdin() from hanging indefinitely on Windows#74
myselfsiddharth wants to merge 1 commit into
supermemoryai:mainfrom
myselfsiddharth:fix/windows-stdin-hang

Conversation

@myselfsiddharth

@myselfsiddharth myselfsiddharth commented Jul 6, 2026

Copy link
Copy Markdown

Summary

Fixes #25

On Windows, piped stdin never emits the end event for hook subprocesses spawned by Claude Code. readStdin() in src/lib/stdin.js waited for that event with no timeout, so every hook (SessionStart, UserPromptSubmit, PreToolUse, Stop) hung at its very first line and burned the full hook timeout before any authentication or API work began.

Changes to readStdin()

  • Eager parse on each chunk: hooks receive exactly one JSON object on stdin, so the promise now resolves as soon as the accumulated input parses as valid JSON. On Windows this means hooks get their input in milliseconds instead of hanging, with no reliance on the timeout at all.
  • 3 second timeout fallback: if no complete input ever arrives, it resolves with {} instead of hanging. All four hook callers already handle empty input gracefully (they fall back to process.cwd() and skip work that needs session_id or transcript_path).
  • Release stdin on settle: pause() plus unref() so the still-open pipe cannot keep the Node process alive after the promise settles, which is the underlying mechanism of the hang.

Unix behavior is unchanged: end still resolves normally, and malformed JSON with a closed stdin still rejects with the same error message as before.

Bundles in plugin/scripts/ were rebuilt with npm run build (the bundle diff churn is from esbuild output formatting; the only source change is src/lib/stdin.js).

Test plan

Verified on Windows 11 by spawning child processes against both the source module and the built bundles:

Scenario Result
Valid JSON, stdin closed (normal Unix path) resolved in ~10 ms
Valid JSON, stdin never closed (the Windows bug) resolved in ~10 ms
No input, stdin never closed resolved with {} after 3 s
Invalid JSON, stdin closed rejects with the same parse error as before
JSON split across chunks, stdin never closed resolved once the object completed
Built recall-hook.cjs with stdin held open process exited in ~200 ms with correct hook output

npx biome check and npm run build both pass.

  • Confirm hooks still behave normally on macOS and Linux

On Windows, piped stdin never emits the 'end' event for hook
subprocesses spawned by Claude Code, so readStdin() waited forever
and every hook burned its full timeout before doing any work.

Fixes supermemoryai#25

Changes to readStdin():
- Parse eagerly on each data chunk: hooks receive a single JSON
  object, so resolve as soon as the accumulated input parses,
  without waiting for 'end' or any timeout
- Add a 3 second timeout fallback that resolves with an empty
  object when no complete input arrives; all callers already
  handle empty input gracefully
- Pause and unref stdin once settled so the open pipe cannot keep
  the process alive

Unix behavior is unchanged: 'end' still resolves normally and
malformed JSON with a closed stdin still rejects with the same
error message.

Bundles in plugin/scripts were rebuilt with npm run build.
@vorflux

vorflux Bot commented Jul 6, 2026

Copy link
Copy Markdown

Vorflux skipped this auto review because this account has reached its Auto Review daily review limit (40/40). You can change this in Auto Review Settings: https://us1.vorflux.com/supermemory/settings?section=pull-requests

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.

[Bug] readStdin() hangs indefinitely on Windows - no timeout on stdin end event

1 participant