Description
Version
23.1.0
Platform
* fails on Debian 12 as a regular user with statically specified ports
* fails on Windows 10 as a regular user with statically specified ports
* does not fail Debian 12 via systemd (as an OS service run as root)
* does not fail if the ports are randomly assigned by specifying port 0 on server invocation
Subsystem
No response
What steps will reproduce the bug?
- execute a child process with command
nmap --open 127.0.0.1
via instruction from any kind of network stream, such as WebSocket message or HTTP request.
const port_map = function (callback:() => void):void {
const command:string = "nmap --open 127.0.0.1";
node.child_process.exec(command, function (error:node_childProcess_ExecException, stdout:string):void {
if (callback !== null) {
callback();
}
});
};
export default port_map;
How often does it reproduce? Is there a required condition?
I can reproduce this 100% from command line in both Debian 12 and Windows 10. 0% from systemd.
What is the expected behavior? Why is that the expected behavior?
child_process exec calls a callback and child_process spawn calls event handlers in accordance with Node API definitions.
What do you see instead?
The application crashes fatally if the error event on the corresponding socket is not trapped immediately at first connection time before other instructions are executed. Assigning a handler to the socket's error event listener later is insufficient, for example assigning the handler from within the following code still results in crashes:
socket.once("data", handler);
The actual error reported by the socket is:
Error: read ECONNRESET
at TCP.onStreamRead (node:internal/stream_base_commons:216:20) {
errno: -104,
code: 'ECONNRESET',
syscall: 'read'
}
The error is the direct result of a child process execution. The corresponding child process executes in response to instructions transmitted on the corresponding socket, but is otherwise not related or associated to the socket.
This following error is the fatal error messaging if the error is not immediately trapped on the corresponding socket.
node:events:485
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at TCP.onStreamRead (node:internal/stream_base_commons:216:20)
Emitted 'error' event on Socket instance at:
at emitErrorNT (node:internal/streams/destroy:170:8)
at emitErrorCloseNT (node:internal/streams/destroy:129:3)
at process.processTicksAndRejections (node:internal/process/task_queues:90:21) {
errno: -104,
code: 'ECONNRESET',
syscall: 'read'
}
The error messaging describes a socket failure, but it is not. It is a child process call only and only on the command specified.
Additional information
Some of the things I have tried:
- I have tried a few other trivial commands like
echo hello
andps -a
. They work without issue. - In exec have tried specifying different shells
/bin/sh
and/bin/bash
- I have tried to call the child process with exec and spawn
- I have tried to call the child process in different ways: manually, recursively, setTimeout, from automated response to a socket message
- I validated that all sockets connected, both http and ws, have assigned event handlers for the error event and I have also isolated all sockets from the problematic behavior.