Skip to content

fix(core): pin pool worker node runtime to parent execPath#1088

Closed
omarshibli wants to merge 1 commit intoweb-infra-dev:mainfrom
omarshibli:os-y26-q1-1
Closed

fix(core): pin pool worker node runtime to parent execPath#1088
omarshibli wants to merge 1 commit intoweb-infra-dev:mainfrom
omarshibli:os-y26-q1-1

Conversation

@omarshibli
Copy link
Copy Markdown

Problem

rstest worker pools did not explicitly pin execPath, so worker runtime selection could drift based on environment/PATH resolution.
That can cause parent/worker Node-version divergence and runtime-specific failures.

Root Cause

Both pool creation points relied on implicit process spawning defaults instead of forcing workers to use the parent process’ Node binary.

Fix

Set execPath: process.execPath in both pool constructors:

  • Forks pool
  • Global setup pool

Files Changed

  • packages/core/src/pool/forks.ts
  • packages/core/src/core/globalSetup.ts
  • packages/core/tests/pool/forksExecPath.test.ts
  • packages/core/tests/core/globalSetupExecPath.test.ts

Verification

  1. Added regression tests first to assert both pools pass execPath: process.execPath.
  2. Confirmed red -> green:
  • With fix removed: new tests fail.
  • With fix restored: new tests pass.
  1. Latest run:
  • pnpm test packages/core/tests/pool/forksExecPath.test.ts packages/core/tests/core/globalSetupExecPath.test.ts
  • Result: 2 passed, 0 failed.

@fi3ework
Copy link
Copy Markdown
Member

fi3ework commented May 6, 2026

  1. Pre-feat(pool): replace tinypool with self-owned worker pool #1171 (tinypool): tinypool's Options type doesn't declare execPath, and tinypool's internal worker.initialize({...}) forwards a hardcoded option whitelist that excludes execPath. The property is dropped before reaching child_process.fork. With or without this PR, worker process.execPath always equals parent's (verified by spawning Node 20 with PATH-first Node 24 — worker stayed on Node 20 without the fix).
  2. Post-feat(pool): replace tinypool with self-owned worker pool #1171 (current main): we now call node:child_process.fork directly. fork()'s execPath defaults to process.execPath per Node spec, so the same invariant holds.
  3. The provided regression tests assert on the tinypool constructor's argument shape, not on the worker's actual runtime — they wouldn't have caught either the tinypool whitelist or any real drift.

Closing as obsolete. Happy to take a follow-up that adds an explicit execPath: process.execPath (defensive/intent-documenting) plus a real end-to-end test that asserts worker.process.execPath === parent.process.execPath against the new pool, if you'd like to take another pass.

@fi3ework fi3ework closed this May 6, 2026
@omarshibli
Copy link
Copy Markdown
Author

Thanks for the follow up.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants