fix(unix): validate spawn-helper exists before calling pty.fork()#917
fix(unix): validate spawn-helper exists before calling pty.fork()#917theJC wants to merge 2 commits intomicrosoft:mainfrom
Conversation
helperPath is computed once at module load time using __dirname. If the application binary moves after the process starts (e.g. a dev build whose repo directory is relocated while the app is running), helperPath becomes stale and posix_spawn returns ENOENT. Previously this propagated into the native layer as 'posix_spawnp failed.' with no path information, and in some cases left V8 heap objects in an inconsistent state that caused a fatal EXC_BREAKPOINT crash ~4 seconds later during a GC pass. This check throws a clean JS error before entering native code, keeps the process alive, and includes the resolved path to aid diagnosis.
|
Tested manually per CONTRIBUTING.md using the Electron example (
|
|
Added a unit test in |
|
@theJC please read the following Contributor License Agreement(CLA). If you agree with the CLA, please reply with the following information.
Contributor License AgreementContribution License AgreementThis Contribution License Agreement (“Agreement”) is agreed to by the party signing below (“You”),
|
Problem
`helperPath` is computed once at module load time using `__dirname`:
```ts
let helperPath = native.dir + '/spawn-helper';
helperPath = path.resolve(__dirname, helperPath);
```
If the application binary moves after the process starts — for example, a dev build whose repository directory is relocated while the app is running — `helperPath` becomes stale. On the next call to `pty.fork()`, `posix_spawn` receives a non-existent path for `argv[0]` and returns `ENOENT`.
Previously this had two bad outcomes:
Fix
Add an `fs.existsSync` guard in the `UnixTerminal` constructor before calling `pty.fork()`. This:
Related
Testing
Unit test added in `src/unixTerminal.test.ts` under the existing `darwin`-only block in `describe('spawn')`. It temporarily renames the `spawn-helper` binary, asserts the constructor throws with a message containing both `"spawn-helper not found"` and the resolved path, then restores the binary in a `finally` block — the same rename-and-restore pattern used by the ptmx fd leak test added in #882. No additional dependencies required.
Manual testing via the Electron example (`examples/electron`) confirmed: