http,async_hooks: keep resource object alive from socket

If `asyncReset()` is used to specify an alternative resource object
to mark a re-used socket in the HTTP Agent implementation,
store that object and keep it alive, because domains rely on GC tracking
for resource objects to manage their own lifetimes, and previously that
resource object might have been garbage-collected too early, leading to
crashes.

Fixes: https://github.com/nodejs/node/issues/30122

PR-URL: https://github.com/nodejs/node/pull/30196
Reviewed-By: Vladimir de Turckheim <vlad2t@hotmail.com>
Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
This commit is contained in:
Anna Henningsen 2019-10-31 15:48:16 +01:00
parent 0673dfc0d8
commit d26a74dca0
No known key found for this signature in database
GPG key ID: 9C63F3A6CD2AD8F9
2 changed files with 106 additions and 0 deletions

View file

@ -44,10 +44,18 @@ const {
// ClientRequest.onSocket(). The Agent is now *strictly*
// concerned with managing a connection pool.
const kReusedHandle = Symbol('kReusedHandle');
class ReusedHandle {
constructor(type, handle) {
this.type = type;
this.handle = handle;
// We need keep the resource object alive from this object, because
// domains rely on GC of the resource object for lifetime tracking.
// TODO(addaleax): This should really apply to all uses of
// AsyncWrap::AsyncReset() when the resource is not the AsyncWrap object
// itself. However, HTTPClientAsyncResource and HTTPServerAsyncResource
// hold on to other objects, inhibiting GC.
handle[kReusedHandle] = this;
}
}