-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
http: add missing async_hooks destroy before asyncReset #23201
http: add missing async_hooks destroy before asyncReset #23201
Conversation
This also adds a test that fails without the change and passes when the fix is applied. I'd like to bring up two questions for potential reviewers:
|
cc @nodejs/http @nodejs/async_hooks |
Emit a destroy before calling asyncReset because otherwise the old async_id never gets destroyed. Refs: nodejs#19859
eef00f1
to
08fcb79
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be preferable to issue the destroy event from C++ (that is, from within src/async_wrap.cc,
void AsyncWrap::AsyncReset(double execution_async_id, bool silent)
)?
I think that might be a good idea, yes. This issue doesn’t seem to be specific to HTTP, but rather generally applies to AsyncWrap
instances that are to be reset?
The test I added has a lot of code in common with test/parallel/test-async-hooks-http-agent.js - should I rather merge my assertion into that?
That’s your call… adding assertions to existing tests isn’t a bad thing in any way, though.
@@ -167,6 +172,9 @@ Agent.prototype.addRequest = function addRequest(req, options, port/* legacy */, | |||
var socket = this.freeSockets[name].shift(); | |||
// Guard against an uninitialized or user supplied Socket. | |||
if (socket._handle && typeof socket._handle.asyncReset === 'function') { | |||
if (destroyHooksExist() && socket._handle.getAsyncId()) { | |||
emitDestroy(socket._handle.getAsyncId()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we do the destroy from JS, can we cache the result of getAsyncId()
? Calls into C++ are, unfortunately, not the cheapest…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This call no longer exists in #23272.
For completeness sake:
Well opinions differ on that, there are a bunch of folks who insist that tests should always only assert one thing. If there are no strong opinions I would keep the tests separate. |
Emit a destroy before calling asyncReset because otherwise the old
async_id never gets destroyed.
Refs: #19859
This fixes one of the two issues described in here: #19859 (comment), namely the missing
destroy
event when an http agent gets reused.Reasoning: When calling
asyncReset
on the socket, we need to be aware that this will overwrite the socket'sasyncId
. TheasyncId
assigned to the socket beforeasyncReset
is then lost, thus, a destroy event will never be emitted for this "old"asyncId
. The addedemitDestroy
makes sure that a matching destroy event is emitted before we assign the newasyncId
inasyncReset
.See also: #23263
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes