From 5a199a905b59b671d4d7a7e35de286df22811a9c Mon Sep 17 00:00:00 2001 From: Andreas Madsen Date: Wed, 22 Nov 2017 18:41:00 +0100 Subject: [PATCH] async_hooks: use scope for defaultTriggerAsyncId Previously the getter would mutate the kDefaultTriggerAsncId value. This refactor changes the setter to bind the current kDefaultTriggerAsncId to a scope, such that the getter doesn't have to mutate its own value. Backport-PR-URL: https://github.com/nodejs/node/pull/18179 PR-URL: https://github.com/nodejs/node/pull/17273 Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/async_hooks.js | 8 ---- lib/dgram.js | 21 +++++---- lib/internal/async_hooks.js | 21 +++++---- lib/net.js | 91 +++++++++++++++++++------------------ src/async_wrap.cc | 11 +++-- src/connection_wrap.cc | 1 - src/env-inl.h | 33 +++++++------- src/env.h | 20 ++++---- src/pipe_wrap.cc | 3 +- src/stream_base-inl.h | 3 +- src/stream_base.cc | 40 +++++++++------- src/tcp_wrap.cc | 9 ++-- src/udp_wrap.cc | 12 +++-- 13 files changed, 144 insertions(+), 129 deletions(-) diff --git a/lib/async_hooks.js b/lib/async_hooks.js index ad5049a6fe57e1..bf07358fd5e2c1 100644 --- a/lib/async_hooks.js +++ b/lib/async_hooks.js @@ -20,7 +20,6 @@ const { // Sensitive Embedder API newUid, getDefaultTriggerAsyncId, - setInitTriggerId, emitInit, emitBefore, emitAfter, @@ -281,13 +280,6 @@ Object.defineProperty(module.exports, 'initTriggerId', { 'Use the AsyncResource default instead.', 'DEP0085') }); -Object.defineProperty(module.exports, 'setInitTriggerId', { - get: internalUtil.deprecate(function() { - return setInitTriggerId; - }, 'async_hooks.setInitTriggerId is deprecated. ' + - 'Use the triggerAsyncId parameter in AsyncResource instead.', 'DEP0085') -}); - Object.defineProperty(module.exports, 'emitInit', { get: internalUtil.deprecate(function() { return emitInit; diff --git a/lib/dgram.js b/lib/dgram.js index f14e6c7890e485..04828155f3a0d7 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -28,7 +28,7 @@ const dns = require('dns'); const util = require('util'); const { isUint8Array } = require('internal/util/types'); const EventEmitter = require('events'); -const { setDefaultTriggerAsyncId } = require('internal/async_hooks'); +const { defaultTriggerAsyncIdScope } = require('internal/async_hooks'); const { UV_UDP_REUSEADDR } = process.binding('constants').os; const { async_id_symbol } = process.binding('async_wrap'); const { nextTick } = require('internal/process/next_tick'); @@ -448,21 +448,24 @@ Socket.prototype.send = function(buffer, } const afterDns = (ex, ip) => { - doSend(ex, this, ip, list, address, port, callback); + defaultTriggerAsyncIdScope( + this[async_id_symbol], + [ex, this, ip, list, address, port, callback], + doSend + ); }; this._handle.lookup(address, afterDns); }; - function doSend(ex, self, ip, list, address, port, callback) { if (ex) { if (typeof callback === 'function') { - callback(ex); + process.nextTick(callback, ex); return; } - self.emit('error', ex); + process.nextTick(() => self.emit('error', ex)); return; } else if (!self._handle) { return; @@ -476,20 +479,18 @@ function doSend(ex, self, ip, list, address, port, callback) { req.callback = callback; req.oncomplete = afterSend; } - // node::SendWrap isn't instantiated and attached to the JS instance of - // SendWrap above until send() is called. So don't set the init trigger id - // until now. - setDefaultTriggerAsyncId(self[async_id_symbol]); + var err = self._handle.send(req, list, list.length, port, ip, !!callback); + if (err && callback) { // don't emit as error, dgram_legacy.js compatibility const ex = exceptionWithHostPort(err, 'send', address, port); - nextTick(self[async_id_symbol], callback, ex); + process.nextTick(callback, ex); } } diff --git a/lib/internal/async_hooks.js b/lib/internal/async_hooks.js index 6b0420c8c71062..366a218b7a95c2 100644 --- a/lib/internal/async_hooks.js +++ b/lib/internal/async_hooks.js @@ -250,9 +250,6 @@ function newUid() { // constructor is complete. function getDefaultTriggerAsyncId() { var defaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; - // Reset value after it's been called so the next constructor doesn't - // inherit it by accident. - async_id_fields[kDefaultTriggerAsyncId] = -1; // If defaultTriggerAsyncId isn't set, use the executionAsyncId if (defaultTriggerAsyncId < 0) defaultTriggerAsyncId = async_id_fields[kExecutionAsyncId]; @@ -260,10 +257,20 @@ function getDefaultTriggerAsyncId() { } -function setDefaultTriggerAsyncId(triggerAsyncId) { +function defaultTriggerAsyncIdScope(triggerAsyncId, opaque, block) { // CHECK(Number.isSafeInteger(triggerAsyncId)) // CHECK(triggerAsyncId > 0) + const oldDefaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; async_id_fields[kDefaultTriggerAsyncId] = triggerAsyncId; + + var ret; + try { + ret = Reflect.apply(block, null, opaque); + } finally { + async_id_fields[kDefaultTriggerAsyncId] = oldDefaultTriggerAsyncId; + } + + return ret; } @@ -285,10 +292,6 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) { // manually means that the embedder must have used getDefaultTriggerAsyncId(). if (triggerAsyncId === null) { triggerAsyncId = getDefaultTriggerAsyncId(); - } else { - // If a triggerAsyncId was passed, any kDefaultTriggerAsyncId still must be - // null'd. - async_id_fields[kDefaultTriggerAsyncId] = -1; } emitInitNative(asyncId, type, triggerAsyncId, resource); @@ -341,7 +344,7 @@ module.exports = { // Sensitive Embedder API newUid, getDefaultTriggerAsyncId, - setDefaultTriggerAsyncId, + defaultTriggerAsyncIdScope, emitInit: emitInitScript, emitBefore: emitBeforeScript, emitAfter: emitAfterScript, diff --git a/lib/net.js b/lib/net.js index bf2a3da97a4dd7..43eb15605ff965 100644 --- a/lib/net.js +++ b/lib/net.js @@ -39,7 +39,7 @@ const { TCPConnectWrap } = process.binding('tcp_wrap'); const { PipeConnectWrap } = process.binding('pipe_wrap'); const { ShutdownWrap, WriteWrap } = process.binding('stream_wrap'); const { async_id_symbol } = process.binding('async_wrap'); -const { newUid, setDefaultTriggerAsyncId } = require('internal/async_hooks'); +const { newUid, defaultTriggerAsyncIdScope } = require('internal/async_hooks'); const { nextTick } = require('internal/process/next_tick'); const errors = require('internal/errors'); const dns = require('dns'); @@ -270,6 +270,14 @@ Socket.prototype._unrefTimer = function _unrefTimer() { timers._unrefActive(s); }; + +function shutdownSocket(self, callback) { + var req = new ShutdownWrap(); + req.oncomplete = callback; + req.handle = self._handle; + return self._handle.shutdown(req); +} + // the user has called .end(), and all the bytes have been // sent out to the other side. function onSocketFinish() { @@ -291,14 +299,9 @@ function onSocketFinish() { if (!this._handle || !this._handle.shutdown) return this.destroy(); - var req = new ShutdownWrap(); - req.oncomplete = afterShutdown; - req.handle = this._handle; - // node::ShutdownWrap isn't instantiated and attached to the JS instance of - // ShutdownWrap above until shutdown() is called. So don't set the init - // trigger id until now. - setDefaultTriggerAsyncId(this[async_id_symbol]); - var err = this._handle.shutdown(req); + var err = defaultTriggerAsyncIdScope( + this[async_id_symbol], [this, afterShutdown], shutdownSocket + ); if (err) return this.destroy(errnoException(err, 'shutdown')); @@ -950,23 +953,15 @@ function internalConnect( req.localAddress = localAddress; req.localPort = localPort; - // node::TCPConnectWrap isn't instantiated and attached to the JS instance - // of TCPConnectWrap above until connect() is called. So don't set the init - // trigger id until now. - setDefaultTriggerAsyncId(self[async_id_symbol]); if (addressType === 4) err = self._handle.connect(req, address, port); else err = self._handle.connect6(req, address, port); - } else { const req = new PipeConnectWrap(); req.address = address; req.oncomplete = afterConnect; - // node::PipeConnectWrap isn't instantiated and attached to the JS instance - // of PipeConnectWrap above until connect() is called. So don't set the - // init trigger id until now. - setDefaultTriggerAsyncId(self[async_id_symbol]); + err = self._handle.connect(req, address, afterConnect); } @@ -1035,7 +1030,9 @@ Socket.prototype.connect = function(...args) { 'string', path); } - internalConnect(this, path); + defaultTriggerAsyncIdScope( + this[async_id_symbol], [this, path], internalConnect + ); } else { lookupAndConnect(this, options); } @@ -1074,7 +1071,11 @@ function lookupAndConnect(self, options) { if (addressType) { nextTick(self[async_id_symbol], function() { if (self.connecting) - internalConnect(self, host, port, addressType, localAddress, localPort); + defaultTriggerAsyncIdScope( + self[async_id_symbol], + [self, host, port, addressType, localAddress, localPort], + internalConnect + ); }); return; } @@ -1095,33 +1096,33 @@ function lookupAndConnect(self, options) { debug('connect: dns options', dnsopts); self._host = host; var lookup = options.lookup || dns.lookup; - setDefaultTriggerAsyncId(self[async_id_symbol]); - lookup(host, dnsopts, function emitLookup(err, ip, addressType) { - self.emit('lookup', err, ip, addressType, host); + defaultTriggerAsyncIdScope(self[async_id_symbol], [], function() { + lookup(host, dnsopts, function emitLookup(err, ip, addressType) { + self.emit('lookup', err, ip, addressType, host); - // It's possible we were destroyed while looking this up. - // XXX it would be great if we could cancel the promise returned by - // the look up. - if (!self.connecting) return; + // It's possible we were destroyed while looking this up. + // XXX it would be great if we could cancel the promise returned by + // the look up. + if (!self.connecting) return; - if (err) { - // net.createConnection() creates a net.Socket object and - // immediately calls net.Socket.connect() on it (that's us). - // There are no event listeners registered yet so defer the - // error event to the next tick. - err.host = options.host; - err.port = options.port; - err.message = err.message + ' ' + options.host + ':' + options.port; - process.nextTick(connectErrorNT, self, err); - } else { - self._unrefTimer(); - internalConnect(self, - ip, - port, - addressType, - localAddress, - localPort); - } + if (err) { + // net.createConnection() creates a net.Socket object and + // immediately calls net.Socket.connect() on it (that's us). + // There are no event listeners registered yet so defer the + // error event to the next tick. + err.host = options.host; + err.port = options.port; + err.message = err.message + ' ' + options.host + ':' + options.port; + process.nextTick(connectErrorNT, self, err); + } else { + self._unrefTimer(); + defaultTriggerAsyncIdScope( + self[async_id_symbol], + [self, ip, port, addressType, localAddress, localPort], + internalConnect + ); + } + }); }); } diff --git a/src/async_wrap.cc b/src/async_wrap.cc index 897cc5a5518fac..bfbc8f222987d4 100644 --- a/src/async_wrap.cc +++ b/src/async_wrap.cc @@ -330,12 +330,13 @@ static void PromiseHook(PromiseHookType type, Local promise, if (parent_wrap == nullptr) { parent_wrap = PromiseWrap::New(env, parent_promise, nullptr, true); } - // get id from parentWrap - double trigger_async_id = parent_wrap->get_async_id(); - env->set_default_trigger_async_id(trigger_async_id); - } - wrap = PromiseWrap::New(env, promise, parent_wrap, silent); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, parent_wrap->get_async_id()); + wrap = PromiseWrap::New(env, promise, parent_wrap, silent); + } else { + wrap = PromiseWrap::New(env, promise, nullptr, silent); + } } CHECK_NE(wrap, nullptr); diff --git a/src/connection_wrap.cc b/src/connection_wrap.cc index b7c1949e11e404..8de77f361dcde4 100644 --- a/src/connection_wrap.cc +++ b/src/connection_wrap.cc @@ -49,7 +49,6 @@ void ConnectionWrap::OnConnection(uv_stream_t* handle, }; if (status == 0) { - env->set_default_trigger_async_id(wrap_data->get_async_id()); // Instantiate the client javascript object and handle. Local client_obj = WrapType::Instantiate(env, wrap_data, diff --git a/src/env-inl.h b/src/env-inl.h index 736271a911c905..51f6ea14ccc666 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -197,23 +197,27 @@ inline void Environment::AsyncHooks::clear_async_id_stack() { async_id_fields_[kTriggerAsyncId] = 0; } -inline Environment::AsyncHooks::InitScope::InitScope( - Environment* env, double init_trigger_async_id) - : env_(env), - async_id_fields_ref_(env->async_hooks()->async_id_fields()) { - if (env_->async_hooks()->fields()[AsyncHooks::kCheck] > 0) { - CHECK_GE(init_trigger_async_id, -1); +inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope + ::DefaultTriggerAsyncIdScope(Environment* env, + double default_trigger_async_id) + : async_id_fields_ref_(env->async_hooks()->async_id_fields()) { + if (env->async_hooks()->fields()[AsyncHooks::kCheck] > 0) { + CHECK_GE(default_trigger_async_id, 0); } - env->async_hooks()->push_async_ids( - async_id_fields_ref_[AsyncHooks::kExecutionAsyncId], - init_trigger_async_id); + + old_default_trigger_async_id_ = + async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId]; + async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId] = + default_trigger_async_id; } -inline Environment::AsyncHooks::InitScope::~InitScope() { - env_->async_hooks()->pop_async_id( - async_id_fields_ref_[AsyncHooks::kExecutionAsyncId]); +inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope + ::~DefaultTriggerAsyncIdScope() { + async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId] = + old_default_trigger_async_id_; } + inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env) : env_(env) { env_->makecallback_cntr_++; @@ -473,17 +477,12 @@ inline double Environment::trigger_async_id() { inline double Environment::get_default_trigger_async_id() { double default_trigger_async_id = async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId]; - async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] = -1; // If defaultTriggerAsyncId isn't set, use the executionAsyncId if (default_trigger_async_id < 0) default_trigger_async_id = execution_async_id(); return default_trigger_async_id; } -inline void Environment::set_default_trigger_async_id(const double id) { - async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] = id; -} - inline double* Environment::heap_statistics_buffer() const { CHECK_NE(heap_statistics_buffer_, nullptr); return heap_statistics_buffer_; diff --git a/src/env.h b/src/env.h index a359c255bc59a8..bbeb86f71a7714 100644 --- a/src/env.h +++ b/src/env.h @@ -422,22 +422,23 @@ class Environment { inline size_t stack_size(); inline void clear_async_id_stack(); // Used in fatal exceptions. - // Used to propagate the trigger_async_id to the constructor of any newly - // created resources using RAII. Instead of needing to pass the - // trigger_async_id along with other constructor arguments. - class InitScope { + // Used to set the kDefaultTriggerAsyncId in a scope. This is instead of + // passing the trigger_async_id along with other constructor arguments. + class DefaultTriggerAsyncIdScope { public: - InitScope() = delete; - explicit InitScope(Environment* env, double init_trigger_async_id); - ~InitScope(); + DefaultTriggerAsyncIdScope() = delete; + explicit DefaultTriggerAsyncIdScope(Environment* env, + double init_trigger_async_id); + ~DefaultTriggerAsyncIdScope(); private: - Environment* env_; AliasedBuffer async_id_fields_ref_; + double old_default_trigger_async_id_; - DISALLOW_COPY_AND_ASSIGN(InitScope); + DISALLOW_COPY_AND_ASSIGN(DefaultTriggerAsyncIdScope); }; + private: friend class Environment; // So we can call the constructor. inline explicit AsyncHooks(v8::Isolate* isolate); @@ -594,7 +595,6 @@ class Environment { inline double execution_async_id(); inline double trigger_async_id(); inline double get_default_trigger_async_id(); - inline void set_default_trigger_async_id(const double id); // List of id's that have been destroyed and need the destroy() cb called. inline std::vector* destroy_async_id_list(); diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index 281ac4d6838dbc..b4f01f08a647a8 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -52,7 +52,8 @@ Local PipeWrap::Instantiate(Environment* env, AsyncWrap* parent, PipeWrap::SocketType type) { EscapableHandleScope handle_scope(env->isolate()); - AsyncHooks::InitScope init_scope(env, parent->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, + parent->get_async_id()); CHECK_EQ(false, env->pipe_constructor_template().IsEmpty()); Local constructor = env->pipe_constructor_template()->GetFunction(); CHECK_EQ(false, constructor.IsEmpty()); diff --git a/src/stream_base-inl.h b/src/stream_base-inl.h index 807e138ef7b6df..eacdb3832c0662 100644 --- a/src/stream_base-inl.h +++ b/src/stream_base-inl.h @@ -138,7 +138,8 @@ void StreamBase::JSMethod(const FunctionCallbackInfo& args) { if (!wrap->IsAlive()) return args.GetReturnValue().Set(UV_EINVAL); - AsyncHooks::InitScope init_scope(handle->env(), handle->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + handle->env(), handle->get_async_id()); args.GetReturnValue().Set((wrap->*Method)(args)); } diff --git a/src/stream_base.cc b/src/stream_base.cc index 11b83c67957da6..34564cadbe777a 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -52,7 +52,7 @@ int StreamBase::Shutdown(const FunctionCallbackInfo& args) { AsyncWrap* wrap = GetAsyncWrap(); CHECK_NE(wrap, nullptr); - env->set_default_trigger_async_id(wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope(env, wrap->get_async_id()); ShutdownWrap* req_wrap = new ShutdownWrap(env, req_wrap_obj, this, @@ -111,7 +111,6 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { size_t storage_size = 0; uint32_t bytes = 0; size_t offset; - AsyncWrap* wrap; WriteWrap* req_wrap; int err; @@ -155,10 +154,14 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { goto done; } - wrap = GetAsyncWrap(); - CHECK_NE(wrap, nullptr); - env->set_default_trigger_async_id(wrap->get_async_id()); - req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite, storage_size); + { + AsyncWrap* wrap = GetAsyncWrap(); + CHECK_NE(wrap, nullptr); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, + wrap->get_async_id()); + req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite, + storage_size); + } offset = 0; if (!all_buffers) { @@ -228,7 +231,6 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo& args) { const char* data = Buffer::Data(args[1]); size_t length = Buffer::Length(args[1]); - AsyncWrap* wrap; WriteWrap* req_wrap; uv_buf_t buf; buf.base = const_cast(data); @@ -244,11 +246,14 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo& args) { goto done; CHECK_EQ(count, 1); - wrap = GetAsyncWrap(); - if (wrap != nullptr) - env->set_default_trigger_async_id(wrap->get_async_id()); // Allocate, or write rest - req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite); + { + AsyncWrap* wrap = GetAsyncWrap(); + CHECK_NE(wrap, nullptr); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, + wrap->get_async_id()); + req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite); + } err = DoWrite(req_wrap, bufs, count, nullptr); req_wrap_obj->Set(env->async(), True(env->isolate())); @@ -278,7 +283,6 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { Local req_wrap_obj = args[0].As(); Local string = args[1].As(); Local send_handle_obj; - AsyncWrap* wrap; if (args[2]->IsObject()) send_handle_obj = args[2].As(); @@ -329,10 +333,14 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { CHECK_EQ(count, 1); } - wrap = GetAsyncWrap(); - if (wrap != nullptr) - env->set_default_trigger_async_id(wrap->get_async_id()); - req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite, storage_size); + { + AsyncWrap* wrap = GetAsyncWrap(); + CHECK_NE(wrap, nullptr); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env, + wrap->get_async_id()); + req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite, + storage_size); + } data = req_wrap->Extra(); diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index 00853df9baf5c8..bdae0ee994360c 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -56,7 +56,8 @@ Local TCPWrap::Instantiate(Environment* env, AsyncWrap* parent, TCPWrap::SocketType type) { EscapableHandleScope handle_scope(env->isolate()); - AsyncHooks::InitScope init_scope(env, parent->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, parent->get_async_id()); CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false); Local constructor = env->tcp_constructor_template()->GetFunction(); CHECK_EQ(constructor.IsEmpty(), false); @@ -293,7 +294,8 @@ void TCPWrap::Connect(const FunctionCallbackInfo& args) { int err = uv_ip4_addr(*ip_address, port, &addr); if (err == 0) { - env->set_default_trigger_async_id(wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, wrap->get_async_id()); ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP); err = uv_tcp_connect(req_wrap->req(), @@ -329,7 +331,8 @@ void TCPWrap::Connect6(const FunctionCallbackInfo& args) { int err = uv_ip6_addr(*ip_address, port, &addr); if (err == 0) { - env->set_default_trigger_async_id(wrap->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, wrap->get_async_id()); ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP); err = uv_tcp_connect(req_wrap->req(), diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index 5ba2be37c7a601..784b36fce95b21 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -347,8 +347,12 @@ void UDPWrap::DoSend(const FunctionCallbackInfo& args, int family) { node::Utf8Value address(env->isolate(), args[4]); const bool have_callback = args[5]->IsTrue(); - env->set_default_trigger_async_id(wrap->get_async_id()); - SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback); + SendWrap* req_wrap; + { + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, wrap->get_async_id()); + req_wrap = new SendWrap(env, req_wrap_obj, have_callback); + } size_t msg_size = 0; MaybeStackBuffer bufs(count); @@ -497,7 +501,9 @@ Local UDPWrap::Instantiate(Environment* env, AsyncWrap* parent, UDPWrap::SocketType type) { EscapableHandleScope scope(env->isolate()); - AsyncHooks::InitScope init_scope(env, parent->get_async_id()); + AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope( + env, parent->get_async_id()); + // If this assert fires then Initialize hasn't been called yet. CHECK_EQ(env->udp_constructor_function().IsEmpty(), false); Local instance = env->udp_constructor_function()