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

Fix memory leak caused by misfiring callback #287

Closed
wants to merge 1 commit into from

Conversation

anandsuresh
Copy link
Contributor

Streams can be ended by calling the .close() or .shutdown() methods
on the Handle instances. Internally, both call the .end() method to
end the stream. However, only the .close() method takes a callback
that eventually frees the HttpParser instance allocated to the stream
socket.

In the event that the .shutdown() method is called before calling the
.close() method, the second call to .end() never fires the callback,
resulting in the leaking of HttpParser instances along with all its
references.

This commit fixes the issue by directly executing the callback provided
to the .close() method in the event the .shutdown() method was
called before the .close() method of the Handle instance.

Streams can be ended by calling the `.close()` or `.shutdown()` methods
on the Handle instances. Internally, both call the `.end()` method to
end the stream. However, only the `.close()` method takes a callback
that eventually frees the HttpParser instance allocated to the stream
socket.

In the event that the `.shutdown()` method is called before calling the
`.close()` method, the second call to `.end()` never fires the callback,
resulting in the leaking of HttpParser instances along with all its
references.

This commit fixes the issue by directly executing the callback provided
to the `.close()` method in the event the `.shutdown()` method was
called before the `.close()` method of the Handle instance.
ok: 'yes'
});
res.end('response');
setTimeout(function() {
Copy link
Contributor Author

@anandsuresh anandsuresh Oct 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not my proudest moment, but it was either this or introducing a nested process.nextTick() in handle.js, which was uglier. The issue is that by the time the test gets around to reading the incoming data from the client, the response has ended, and the call to stream.end() ends up terminating the whole stream before the end event fires on the request object.

Also, it was only the HTTP/2 tests that were failing. The SPDY tests were working fine.

Copy link
Collaborator

@indutny indutny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, sorry for delay.

if (stream._spdyState.isServer && stream._writableState.ending) {
process.nextTick(callback);
} else {
stream.end(callback);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yikes, good catch!

@@ -91,4 +91,3 @@ exports.everyConfig = function everyConfig(body) {
});
});
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Superfluous change, will fix it myself.

@indutny
Copy link
Collaborator

indutny commented Oct 12, 2016

@anandsuresh the tests doesn't seem to fail without changes to lib/ folder... I clearly see the issue here, but looks like the tests don't reproduce it.

@indutny
Copy link
Collaborator

indutny commented Oct 12, 2016

I've managed to create a test for it, but unfortunately this one starts fail:

  1. SPDY Server h2 ssl mode should process POST request:
    Error: timeout of 2000ms exceeded. Ensure the done() callback is being called in this test.

Looking into this.

@anandsuresh
Copy link
Contributor Author

That's the error I see at my end when I ran the tests. Running node v4.5.0.

On Wed, Oct 12, 2016, 6:45 AM Fedor Indutny notifications@github.com
wrote:

I've managed to create a test for it, but unfortunately this one starts
fail:

  1. SPDY Server h2 ssl mode should process POST request:
    Error: timeout of 2000ms exceeded. Ensure the done() callback is being
    called in this test.

Looking into this.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#287 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA-tuUu4tD7TmJpul01oLg67fevM9Ho7ks5qzORrgaJpZM4KS_Z2
.

@indutny
Copy link
Collaborator

indutny commented Oct 12, 2016

Landed with fixes in 6a2e14b. Turns out we should have used setImmediate there.

@indutny indutny closed this Oct 12, 2016
@indutny
Copy link
Collaborator

indutny commented Oct 12, 2016

Thank you!

@indutny
Copy link
Collaborator

indutny commented Oct 12, 2016

See nodejs/node#9066

@anandsuresh
Copy link
Contributor Author

@indutny That is pretty damn sweet!!! Thanks for the merge/publish.

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

Successfully merging this pull request may close these issues.

2 participants