Search code examples
node.jswindowsipcchild-processspawn

Node child_process.spawn bad file descriptor on windows with ipc


I am trying to spawn a command in node with ipc option via child_process spawn.

What I call:

const {spawn} = require('child_process');
const cmd = spawn('npm', ['-v'], {
    shell: true,
    stdio: ['inherit', 'inherit', 'inherit', 'ipc']
});
cmd.on('message', (msg) => console.log(msg));

What I get:

child_process.js:122
  p.open(fd);

Error: EBADF: bad file descriptor, uv_pipe_open

Child (child_process.js:122:5)
    at setupChildProcessIpcChannel (internal/bootstrap/pre_execution.js:329:30)
    at prepareMainThreadExecution (internal/bootstrap/pre_execution.js:54:3)
    at internal/main/run_main_module.js:7:1 {
  errno: -4083,
  code: 'EBADF',
  syscall: 'uv_pipe_open'
}

This happnes only in special configuration:

  1. on windows
  2. with 'ipc' option
  3. spawned command is something in js
    will fail: another.js, npm
    will not fail: node

There is a closed issue that's not much useful.

I need the shell: true for cross-platform compatibility according to this article.

Also this issue seems related but I am not smarter after reading it.

node v12.18.3

Thanks for help.


Solution

  • you cannot use 'ipc' with npm, because npm "binary" is a shell script, not a node process (see https://github.com/npm/cli/tree/latest/bin)

    documentation says

    Accessing the IPC channel fd in any way other than process.send() or using the IPC channel with a child process that is not a Node.js instance is not supported.

    for another.js, either use fork (will always work) or spawn('node', 'another.js') which should work if you're not using a node shim (like nodist)