Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Socket recycling causes memory leaks #399

Closed
timdp opened this issue Oct 30, 2017 · 0 comments
Closed

Socket recycling causes memory leaks #399

timdp opened this issue Oct 30, 2017 · 0 comments
Labels
bug Something does not work as it should ✭ help wanted ✭

Comments

@timdp
Copy link

timdp commented Oct 30, 2017

If sockets are recycled, in our case because we're using agentkeepalive as the agent, got's listeners don't always get removed from the socket after it's done its thing. We validated this by instrumenting the connect listener to store a unique ID on every new request ...

// At the top
let count = 0

// In requestAsEventEmitter()
req.connection.on('connect', () => {
  req.connection.__id = req.connection.__id || ++count
  console.log('connect', req.connection.__id)

... and then firing a few requests in sequence using the same socket:

const got = require('got')
const Agent = require('agentkeepalive')

const agent = new Agent({timeout: 100, maxSockets: 1})

;(async () => {
  for (let i = 0; i < 3; i++) {
    await got('http://localhost:31337', {agent})
  }
})()

For the first request, the socket connection listener is hit once; for the second, twice; for the third, thrice; etc. So clearly, something isn't getting cleaned up.

Of course, creating lots of internal state that isn't garbage-collected creates quite a big issue. So unless we're missing something, perhaps it should be made clear that recycling sockets isn't supported for the time being. In the longer term, got should probably clean up after itself even if the socket isn't disposed.

This wasn't the case with version 6, so presumably, since version 7, one of the closures in requestAsEventEmitter() is leaky. In general, personally, I'm a fan of using .once() where possible, and calling .removeEventListener() explicitly whenever I can. I feel like that would also be the more prudent approach here.

This was originally reported by @pietermees as part of his investigation for #353. The EventEmitter leak warning there actually wasn't a red herring at all.

Thanks!

@sindresorhus sindresorhus added bug Something does not work as it should ✭ help wanted ✭ labels Nov 8, 2017
sindresorhus added a commit that referenced this issue Nov 16, 2017
Fixes #399

Currently when you run the Got tests it outputs warnings about EventEmitter memory leaks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something does not work as it should ✭ help wanted ✭
Projects
None yet
Development

No branches or pull requests

2 participants