Sitelet https://github.com/nodejs/node/issues/35923
Skip to content

No error is emitted on response destroy when socket is already destroyed #35923

Description

@szmarczak
  • Version: 10.x.x, 12.x.x, 14.x.x, 15.x.x
  • Platform: Linux solus 5.6.19-159.current #1 SMP PREEMPT Fri Oct 16 17:49:06 UTC 2020 x86_64 GNU/Linux
  • Subsystem: http

What steps will reproduce the bug?

const http = require('http');

const request = http.get('http://httpbin.org/anything', response => {
    setTimeout(() => {
        console.log(`request.destroyed = ${request.destroyed}`);
        console.log(`response.destroyed = ${response.destroyed}`);
        
        response.destroy(new Error('failure'));
    }, 1000);
});

How often does it reproduce? Is there a required condition?

Always.

What is the expected behavior?

An error with a message failure.

What do you see instead?

No error.

Additional information

While I understand that request is destroyed on socket close, the response.destroy logic is broken:

node/lib/_http_incoming.js

Lines 121 to 125 in c1da528

IncomingMessage.prototype.destroy = function destroy(error) {
if (this.socket)
this.socket.destroy(error);
return this;
};

The error is not thrown because the socket has been destroyed. Although the response has not.

Activity

  1. changed the title [-]No error is emitted on response when socket is destroyed[/-] [+]No error is emitted on response destroy when socket is already destroyed[/+] on Nov 2, 2020
  2. added
    httpIssues and PRs related to the http subsystem.
    on Nov 2, 2020
  3. xamgore commented on May 17, 2021

    @xamgore

    Same behaviour in v16.1.0. Possibly @jasnell should keep in mind the issue when implementing HTTP3?

  4. added a commit that references this issue on Sep 5, 2023
  5. avivkeller commented on Jul 11, 2024

    @avivkeller
    Member
    const http = require('http');
    
    const request = http.get('http://httpbin.org/anything', response => {
        setTimeout(() => {
            console.log(`request.destroyed = ${request.destroyed}`);
            console.log(`response.destroyed = ${response.destroyed}`);
            
            response.destroy(new Error('failure'));
        }, 1000);
    });
    request.destroyed = false
    response.destroyed = false
    node:events:498
          throw er; // Unhandled 'error' event
          ^
    
    Error: failure
        at Timeout._onTimeout (/XXX/repro.js:8:26)
        at listOnTimeout (node:internal/timers:581:17)
        at process.processTimers (node:internal/timers:519:7)
    Emitted 'error' event on ClientRequest instance at:
        at Socket.socketErrorListener (node:_http_client:502:9)
        at Socket.emit (node:events:532:35)
        at emitErrorNT (node:internal/streams/destroy:170:8)
        at emitErrorCloseNT (node:internal/streams/destroy:129:3)
        at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
    
    Node.js v22.4.1
    

    AFAICT,this is no longer reproducible. If you disagree, feel free to re-open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    httpIssues and PRs related to the http subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions