I am trying to use Node-Pty to run shell commands from within Electron. After each command finishes executing, I need to know that it has finished executing and get its return code.
Currently I'm using the following approach:
export const spawn = async ({
cmd,
dir,
}: {
cmd: string;
dir: string;
}): Promise<number> => {
const ptyProcess = pty.spawn('bash', ['-c', cmd], {
name: 'xterm-color',
cols: 80,
rows: 10,
cwd: dir,
env: { ...process.env },
});
ptyProcess.onData((ptyData) => {
console.log({ ptyData });
});
return new Promise<number>((resolve) => {
ptyProcess.onExit((x) => {
resolve(x.exitCode);
});
});
};
This is working well for a while, but it seems that eventually Node-Pty fails. I can repro this consistently using the following code:
for (let i = 1; i <= 1000; i++) {
await spawn({ cmd: `echo hello ${i}`, dir: '~', mainWindow });
}
It fails for me after iteration number 505 with the following error:
Error: posix_spawnp failed.
at new UnixTerminal (/Users/dcentore/Dropbox/Projects/Derevo/release/app/node_modules/node-pty/src/unixTerminal.ts:114:22)
at Object.spawn (/Users/dcentore/Dropbox/Projects/Derevo/release/app/node_modules/node-pty/src/index.ts:30:10)
at spawn (/Users/dcentore/Dropbox/Projects/Derevo/src/main/gitlib/git-write.ts:74:20)
at /Users/dcentore/Dropbox/Projects/Derevo/src/main/main.ts:53:16
at async WebContents.<anonymous> (node:electron/js2c/browser_init:2:89579)
I believe this is because I'm running up against the Mac kern.tty.ptmx_max
(set to 511 on my machine). I assume this means I'm not closing the node-pty instances correctly, but I'm struggling to figure out how to actually do that.
How can I close the node-pty instances correctly so I can indefinitely create new ones?