Skip to content

send() can hang due to http2 client.request() apparently having no timeout #24

@TysonAndre

Description

@TysonAndre

It seems like many connection timeouts and socket timeout customizations were taken out, and if there are networking issues, I'm concerned that requests to send() could hang forever (until the server ran out of memory?).

  • Memory rose, probably because this was an express app waiting for send() to finish.
  • I was seeing similar issues in node 12, but I think the spikes in send() request duration did not last arbitrarily long. There was refactoring of the http2 server to change the timeout from 120 seconds to no timeout, but I can't imagine why the client would be affected

https://nodejs.org/api/http2.html#http2_http2_connect_authority_options_listener mentions options are passed to net.connect.
https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback (That doesn't look like the correct thing - I probably want the timeout to apply to requests instead)

Similar to node-apn#665
Mentioned in #23


https://nodejs.org/api/http2.html#http2_http2stream_settimeout_msecs_callback may be what I want added to ensure that the - there's examples in the documentation. Instead of NGHTTP2_CANCEL, I may want to close the client and destroy it asynchronously if requests hang for too long.

I'm assuming that each request calling req.setTimeout is its own timeout - otherwise it could get extended indefinitely

const http2 = require('http2');
const client = http2.connect('http://example.org:8000');
const { NGHTTP2_CANCEL } = http2.constants;
const req = client.request({ ':path': '/' });

// Cancel the stream if there's no activity after 5 seconds
// Instead of NGHTTP2_CANCEL, I want to close the client and destroy it asynchronously if requests hang for too long.
// Not sure what new errors that would cause this to need to handle.
// This should also use the logger to indicate that node is cancelling the stream because it took too long.
// 5 seconds may be too low for a default for a wide variety of use cases - consider using a higher timeout and making this configurable
req.setTimeout(5000, () => req.close(NGHTTP2_CANCEL));

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions