Skip to content

TLSWrap objects grow with HTTP keep-alive enabled until out of memory error occurs #33468

Closed
@mgilbey

Description

@mgilbey
  • Version:
$ node -p process.versions
{
  node: '14.2.0',
  v8: '8.1.307.31-node.33',
  uv: '1.37.0',
  zlib: '1.2.11',
  brotli: '1.0.7',
  ares: '1.16.0',
  modules: '83',
  nghttp2: '1.40.0',
  napi: '6',
  llhttp: '2.0.4',
  openssl: '1.1.1g',
  cldr: '36.1',
  icu: '66.1',
  tz: '2019c',
  unicode: '13.0'
}
  • Platform: Darwin <host> 19.4.0 Darwin Kernel Version 19.4.0: Wed Mar 4 22:28:40 PST 2020; root:xnu-6153.101.6~15/RELEASE_X86_64 x86_64 and node docker image node:13.13.0-alpine

  • Subsystem: https

What steps will reproduce the bug?

I have created a script to reproduce at https://github.com/mgilbey/node-tls-wrap

The script runs a TLS server and https Agent to be self contained, but only the Agent is needed to reproduce the problem with a HTTPS server to connect to. The classes are only used to help identify which objects are holding references in the heap snapshots.

The script will open 100 connections, send and receive two HTTP requests on each connection (demonstrating keep-alive functions as expected) and then lets the sockets close due to the keep-alive timeout. This repeats five times, leaving 501 TLSWrap objects in memory. The scripts forces a garbage collection, and then collects a heap dump before exiting.

The agent reports the expected number of active / free sockets (never more than 100).

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

The script will consistently reproduce the issue.

I believe the salient points for reproduction are:

  • https Agent with keepAlive enabled
  • The number of open sockets never exceeds the maxSockets Agent option.
  • Sockets are closed due to the keepAlive timeout specified by the Agent being reached.

What is the expected behavior?

TLSWrap and TLSSocket objects are garbage collected when the socket from the agent is closed due to the keep-alive timeout, and no further keep-alive socket re-use is possible.

What do you see instead?

TLSWrap and TLSSocket objects will grow in memory until the old-space heap limits are reached at e.g. 10 or 300 MB limits. The number of TLSWrap and TLSSocket objects in memory will exceed the maxSockets, maxFreeSockets or maxCachedSessions Agent options.

An allocation timeline and heap snapshot are also included in the repository.

image

Each TLSWrap object has four retainers, although none appear to be the https Agent.

image

Additional information

To demonstrate the process crashing due to heap limits, run with --max-old-space-size=10 and increase the number of iterations on line 128 to 50. You can increase heap and the number of iterations should you be more patient.

The issue does not reproduce with the http Agent.

The cause appears to be very similar to resolved issue #19859 that affected the http Agent, particularly the reference to the open sockets being less than the maxSockets option.

Metadata

Metadata

Assignees

No one assigned

    Labels

    httpIssues or PRs related to the http subsystem.httpsIssues or PRs related to the https subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions