Skip to content

Child process breaks on command #55802

Open
@prettydiff

Description

@prettydiff

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?

  1. 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:

  1. I have tried a few other trivial commands like echo hello and ps -a. They work without issue.
  2. In exec have tried specifying different shells /bin/sh and /bin/bash
  3. I have tried to call the child process with exec and spawn
  4. I have tried to call the child process in different ways: manually, recursively, setTimeout, from automated response to a socket message
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs more infoIssues without a valid reproduction.stalledIssues and PRs that are stalled.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions