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.

PR-URL: https://github.com/nodejs/node/pull/17273
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Andreas Madsen 2017-11-22 18:41:00 +01:00
parent 0784b0440c
commit 3b8da4cbe8
No known key found for this signature in database
GPG Key ID: 2FEE61B3C9E40F20
12 changed files with 142 additions and 121 deletions

View File

@ -28,7 +28,7 @@ const dns = require('dns');
const util = require('util'); const util = require('util');
const { isUint8Array } = require('internal/util/types'); const { isUint8Array } = require('internal/util/types');
const EventEmitter = require('events'); 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 { UV_UDP_REUSEADDR } = process.binding('constants').os;
const { async_id_symbol } = process.binding('async_wrap'); const { async_id_symbol } = process.binding('async_wrap');
const { nextTick } = require('internal/process/next_tick'); const { nextTick } = require('internal/process/next_tick');
@ -450,21 +450,24 @@ Socket.prototype.send = function(buffer,
} }
const afterDns = (ex, ip) => { 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); this._handle.lookup(address, afterDns);
}; };
function doSend(ex, self, ip, list, address, port, callback) { function doSend(ex, self, ip, list, address, port, callback) {
if (ex) { if (ex) {
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(ex); process.nextTick(callback, ex);
return; return;
} }
self.emit('error', ex); process.nextTick(() => self.emit('error', ex));
return; return;
} else if (!self._handle) { } else if (!self._handle) {
return; return;
@ -478,20 +481,18 @@ function doSend(ex, self, ip, list, address, port, callback) {
req.callback = callback; req.callback = callback;
req.oncomplete = afterSend; 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, var err = self._handle.send(req,
list, list,
list.length, list.length,
port, port,
ip, ip,
!!callback); !!callback);
if (err && callback) { if (err && callback) {
// don't emit as error, dgram_legacy.js compatibility // don't emit as error, dgram_legacy.js compatibility
const ex = exceptionWithHostPort(err, 'send', address, port); const ex = exceptionWithHostPort(err, 'send', address, port);
nextTick(self[async_id_symbol], callback, ex); process.nextTick(callback, ex);
} }
} }

View File

@ -250,9 +250,6 @@ function newUid() {
// constructor is complete. // constructor is complete.
function getDefaultTriggerAsyncId() { function getDefaultTriggerAsyncId() {
var defaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId]; 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 isn't set, use the executionAsyncId
if (defaultTriggerAsyncId < 0) if (defaultTriggerAsyncId < 0)
defaultTriggerAsyncId = async_id_fields[kExecutionAsyncId]; defaultTriggerAsyncId = async_id_fields[kExecutionAsyncId];
@ -260,10 +257,20 @@ function getDefaultTriggerAsyncId() {
} }
function setDefaultTriggerAsyncId(triggerAsyncId) { function defaultTriggerAsyncIdScope(triggerAsyncId, opaque, block) {
// CHECK(Number.isSafeInteger(triggerAsyncId)) // CHECK(Number.isSafeInteger(triggerAsyncId))
// CHECK(triggerAsyncId > 0) // CHECK(triggerAsyncId > 0)
const oldDefaultTriggerAsyncId = async_id_fields[kDefaultTriggerAsyncId];
async_id_fields[kDefaultTriggerAsyncId] = triggerAsyncId; 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(). // manually means that the embedder must have used getDefaultTriggerAsyncId().
if (triggerAsyncId === null) { if (triggerAsyncId === null) {
triggerAsyncId = getDefaultTriggerAsyncId(); 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); emitInitNative(asyncId, type, triggerAsyncId, resource);
@ -341,7 +344,7 @@ module.exports = {
// Internal Embedder API // Internal Embedder API
newUid, newUid,
getDefaultTriggerAsyncId, getDefaultTriggerAsyncId,
setDefaultTriggerAsyncId, defaultTriggerAsyncIdScope,
emitInit: emitInitScript, emitInit: emitInitScript,
emitBefore: emitBeforeScript, emitBefore: emitBeforeScript,
emitAfter: emitAfterScript, emitAfter: emitAfterScript,

View File

@ -43,7 +43,7 @@ const { TCPConnectWrap } = process.binding('tcp_wrap');
const { PipeConnectWrap } = process.binding('pipe_wrap'); const { PipeConnectWrap } = process.binding('pipe_wrap');
const { ShutdownWrap, WriteWrap } = process.binding('stream_wrap'); const { ShutdownWrap, WriteWrap } = process.binding('stream_wrap');
const { async_id_symbol } = process.binding('async_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 { nextTick } = require('internal/process/next_tick');
const errors = require('internal/errors'); const errors = require('internal/errors');
const dns = require('dns'); const dns = require('dns');
@ -277,6 +277,14 @@ Socket.prototype._unrefTimer = function _unrefTimer() {
timers._unrefActive(s); 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 // the user has called .end(), and all the bytes have been
// sent out to the other side. // sent out to the other side.
function onSocketFinish() { function onSocketFinish() {
@ -298,14 +306,9 @@ function onSocketFinish() {
if (!this._handle || !this._handle.shutdown) if (!this._handle || !this._handle.shutdown)
return this.destroy(); return this.destroy();
var req = new ShutdownWrap(); var err = defaultTriggerAsyncIdScope(
req.oncomplete = afterShutdown; this[async_id_symbol], [this, afterShutdown], shutdownSocket
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);
if (err) if (err)
return this.destroy(errnoException(err, 'shutdown')); return this.destroy(errnoException(err, 'shutdown'));
@ -945,23 +948,15 @@ function internalConnect(
req.localAddress = localAddress; req.localAddress = localAddress;
req.localPort = localPort; 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) if (addressType === 4)
err = self._handle.connect(req, address, port); err = self._handle.connect(req, address, port);
else else
err = self._handle.connect6(req, address, port); err = self._handle.connect6(req, address, port);
} else { } else {
const req = new PipeConnectWrap(); const req = new PipeConnectWrap();
req.address = address; req.address = address;
req.oncomplete = afterConnect; 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); err = self._handle.connect(req, address, afterConnect);
} }
@ -1030,7 +1025,9 @@ Socket.prototype.connect = function(...args) {
'string', 'string',
path); path);
} }
internalConnect(this, path); defaultTriggerAsyncIdScope(
this[async_id_symbol], [this, path], internalConnect
);
} else { } else {
lookupAndConnect(this, options); lookupAndConnect(this, options);
} }
@ -1073,7 +1070,11 @@ function lookupAndConnect(self, options) {
if (addressType) { if (addressType) {
nextTick(self[async_id_symbol], function() { nextTick(self[async_id_symbol], function() {
if (self.connecting) if (self.connecting)
internalConnect(self, host, port, addressType, localAddress, localPort); defaultTriggerAsyncIdScope(
self[async_id_symbol],
[self, host, port, addressType, localAddress, localPort],
internalConnect
);
}); });
return; return;
} }
@ -1097,7 +1098,7 @@ function lookupAndConnect(self, options) {
debug('connect: dns options', dnsopts); debug('connect: dns options', dnsopts);
self._host = host; self._host = host;
var lookup = options.lookup || dns.lookup; var lookup = options.lookup || dns.lookup;
setDefaultTriggerAsyncId(self[async_id_symbol]); defaultTriggerAsyncIdScope(self[async_id_symbol], [], function() {
lookup(host, dnsopts, function emitLookup(err, ip, addressType) { lookup(host, dnsopts, function emitLookup(err, ip, addressType) {
self.emit('lookup', err, ip, addressType, host); self.emit('lookup', err, ip, addressType, host);
@ -1117,14 +1118,14 @@ function lookupAndConnect(self, options) {
process.nextTick(connectErrorNT, self, err); process.nextTick(connectErrorNT, self, err);
} else { } else {
self._unrefTimer(); self._unrefTimer();
internalConnect(self, defaultTriggerAsyncIdScope(
ip, self[async_id_symbol],
port, [self, ip, port, addressType, localAddress, localPort],
addressType, internalConnect
localAddress, );
localPort);
} }
}); });
});
} }

View File

@ -308,12 +308,13 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
if (parent_wrap == nullptr) { if (parent_wrap == nullptr) {
parent_wrap = PromiseWrap::New(env, parent_promise, nullptr, true); 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);
}
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(
env, parent_wrap->get_async_id());
wrap = PromiseWrap::New(env, promise, parent_wrap, silent); wrap = PromiseWrap::New(env, promise, parent_wrap, silent);
} else {
wrap = PromiseWrap::New(env, promise, nullptr, silent);
}
} }
CHECK_NE(wrap, nullptr); CHECK_NE(wrap, nullptr);

View File

@ -49,7 +49,6 @@ void ConnectionWrap<WrapType, UVType>::OnConnection(uv_stream_t* handle,
}; };
if (status == 0) { if (status == 0) {
env->set_default_trigger_async_id(wrap_data->get_async_id());
// Instantiate the client javascript object and handle. // Instantiate the client javascript object and handle.
Local<Object> client_obj = WrapType::Instantiate(env, Local<Object> client_obj = WrapType::Instantiate(env,
wrap_data, wrap_data,

View File

@ -176,23 +176,27 @@ inline void Environment::AsyncHooks::clear_async_id_stack() {
async_id_fields_[kTriggerAsyncId] = 0; async_id_fields_[kTriggerAsyncId] = 0;
} }
inline Environment::AsyncHooks::InitScope::InitScope( inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope
Environment* env, double init_trigger_async_id) ::DefaultTriggerAsyncIdScope(Environment* env,
: env_(env), double default_trigger_async_id)
async_id_fields_ref_(env->async_hooks()->async_id_fields()) { : async_id_fields_ref_(env->async_hooks()->async_id_fields()) {
if (env_->async_hooks()->fields()[AsyncHooks::kCheck] > 0) { if (env->async_hooks()->fields()[AsyncHooks::kCheck] > 0) {
CHECK_GE(init_trigger_async_id, -1); CHECK_GE(default_trigger_async_id, 0);
} }
env->async_hooks()->push_async_ids(
async_id_fields_ref_[AsyncHooks::kExecutionAsyncId], old_default_trigger_async_id_ =
init_trigger_async_id); async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId];
async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId] =
default_trigger_async_id;
} }
inline Environment::AsyncHooks::InitScope::~InitScope() { inline Environment::AsyncHooks::DefaultTriggerAsyncIdScope
env_->async_hooks()->pop_async_id( ::~DefaultTriggerAsyncIdScope() {
async_id_fields_ref_[AsyncHooks::kExecutionAsyncId]); async_id_fields_ref_[AsyncHooks::kDefaultTriggerAsyncId] =
old_default_trigger_async_id_;
} }
inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env) inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env)
: env_(env) { : env_(env) {
env_->makecallback_cntr_++; env_->makecallback_cntr_++;
@ -456,17 +460,12 @@ inline double Environment::trigger_async_id() {
inline double Environment::get_default_trigger_async_id() { inline double Environment::get_default_trigger_async_id() {
double default_trigger_async_id = double default_trigger_async_id =
async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId]; async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId];
async_hooks()->async_id_fields()[AsyncHooks::kDefaultTriggerAsyncId] = -1;
// If defaultTriggerAsyncId isn't set, use the executionAsyncId // If defaultTriggerAsyncId isn't set, use the executionAsyncId
if (default_trigger_async_id < 0) if (default_trigger_async_id < 0)
default_trigger_async_id = execution_async_id(); default_trigger_async_id = execution_async_id();
return default_trigger_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 { inline double* Environment::heap_statistics_buffer() const {
CHECK_NE(heap_statistics_buffer_, nullptr); CHECK_NE(heap_statistics_buffer_, nullptr);
return heap_statistics_buffer_; return heap_statistics_buffer_;

View File

@ -402,22 +402,23 @@ class Environment {
inline size_t stack_size(); inline size_t stack_size();
inline void clear_async_id_stack(); // Used in fatal exceptions. inline void clear_async_id_stack(); // Used in fatal exceptions.
// Used to propagate the trigger_async_id to the constructor of any newly // Used to set the kDefaultTriggerAsyncId in a scope. This is instead of
// created resources using RAII. Instead of needing to pass the // passing the trigger_async_id along with other constructor arguments.
// trigger_async_id along with other constructor arguments. class DefaultTriggerAsyncIdScope {
class InitScope {
public: public:
InitScope() = delete; DefaultTriggerAsyncIdScope() = delete;
explicit InitScope(Environment* env, double init_trigger_async_id); explicit DefaultTriggerAsyncIdScope(Environment* env,
~InitScope(); double init_trigger_async_id);
~DefaultTriggerAsyncIdScope();
private: private:
Environment* env_;
AliasedBuffer<double, v8::Float64Array> async_id_fields_ref_; AliasedBuffer<double, v8::Float64Array> async_id_fields_ref_;
double old_default_trigger_async_id_;
DISALLOW_COPY_AND_ASSIGN(InitScope); DISALLOW_COPY_AND_ASSIGN(DefaultTriggerAsyncIdScope);
}; };
private: private:
friend class Environment; // So we can call the constructor. friend class Environment; // So we can call the constructor.
inline explicit AsyncHooks(v8::Isolate* isolate); inline explicit AsyncHooks(v8::Isolate* isolate);
@ -559,7 +560,6 @@ class Environment {
inline double execution_async_id(); inline double execution_async_id();
inline double trigger_async_id(); inline double trigger_async_id();
inline double get_default_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. // List of id's that have been destroyed and need the destroy() cb called.
inline std::vector<double>* destroy_async_id_list(); inline std::vector<double>* destroy_async_id_list();

View File

@ -53,7 +53,8 @@ Local<Object> PipeWrap::Instantiate(Environment* env,
AsyncWrap* parent, AsyncWrap* parent,
PipeWrap::SocketType type) { PipeWrap::SocketType type) {
EscapableHandleScope handle_scope(env->isolate()); 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()); CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
Local<Function> constructor = env->pipe_constructor_template()->GetFunction(); Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
CHECK_EQ(false, constructor.IsEmpty()); CHECK_EQ(false, constructor.IsEmpty());

View File

@ -143,7 +143,8 @@ void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
if (!wrap->IsAlive()) if (!wrap->IsAlive())
return args.GetReturnValue().Set(UV_EINVAL); 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)); args.GetReturnValue().Set((wrap->*Method)(args));
} }

View File

@ -52,7 +52,7 @@ int StreamBase::Shutdown(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap = GetAsyncWrap(); AsyncWrap* wrap = GetAsyncWrap();
CHECK_NE(wrap, nullptr); 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, ShutdownWrap* req_wrap = new ShutdownWrap(env,
req_wrap_obj, req_wrap_obj,
this); this);
@ -109,7 +109,6 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
size_t storage_size = 0; size_t storage_size = 0;
uint32_t bytes = 0; uint32_t bytes = 0;
size_t offset; size_t offset;
AsyncWrap* wrap;
WriteWrap* req_wrap; WriteWrap* req_wrap;
int err; int err;
@ -153,10 +152,13 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
goto done; goto done;
} }
wrap = GetAsyncWrap(); {
AsyncWrap* wrap = GetAsyncWrap();
CHECK_NE(wrap, nullptr); CHECK_NE(wrap, nullptr);
env->set_default_trigger_async_id(wrap->get_async_id()); AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env,
wrap->get_async_id());
req_wrap = WriteWrap::New(env, req_wrap_obj, this, storage_size); req_wrap = WriteWrap::New(env, req_wrap_obj, this, storage_size);
}
offset = 0; offset = 0;
if (!all_buffers) { if (!all_buffers) {
@ -227,7 +229,6 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
const char* data = Buffer::Data(args[1]); const char* data = Buffer::Data(args[1]);
size_t length = Buffer::Length(args[1]); size_t length = Buffer::Length(args[1]);
AsyncWrap* wrap;
WriteWrap* req_wrap; WriteWrap* req_wrap;
uv_buf_t buf; uv_buf_t buf;
buf.base = const_cast<char*>(data); buf.base = const_cast<char*>(data);
@ -243,11 +244,14 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
goto done; goto done;
CHECK_EQ(count, 1); CHECK_EQ(count, 1);
wrap = GetAsyncWrap();
if (wrap != nullptr)
env->set_default_trigger_async_id(wrap->get_async_id());
// Allocate, or write rest // Allocate, or write rest
{
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); req_wrap = WriteWrap::New(env, req_wrap_obj, this);
}
err = DoWrite(req_wrap, bufs, count, nullptr); err = DoWrite(req_wrap, bufs, count, nullptr);
if (HasWriteQueue()) if (HasWriteQueue())
@ -278,7 +282,6 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
Local<Object> req_wrap_obj = args[0].As<Object>(); Local<Object> req_wrap_obj = args[0].As<Object>();
Local<String> string = args[1].As<String>(); Local<String> string = args[1].As<String>();
Local<Object> send_handle_obj; Local<Object> send_handle_obj;
AsyncWrap* wrap;
if (args[2]->IsObject()) if (args[2]->IsObject())
send_handle_obj = args[2].As<Object>(); send_handle_obj = args[2].As<Object>();
@ -329,10 +332,13 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
CHECK_EQ(count, 1); CHECK_EQ(count, 1);
} }
wrap = GetAsyncWrap(); {
if (wrap != nullptr) AsyncWrap* wrap = GetAsyncWrap();
env->set_default_trigger_async_id(wrap->get_async_id()); CHECK_NE(wrap, nullptr);
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(env,
wrap->get_async_id());
req_wrap = WriteWrap::New(env, req_wrap_obj, this, storage_size); req_wrap = WriteWrap::New(env, req_wrap_obj, this, storage_size);
}
data = req_wrap->Extra(); data = req_wrap->Extra();

View File

@ -56,7 +56,8 @@ Local<Object> TCPWrap::Instantiate(Environment* env,
AsyncWrap* parent, AsyncWrap* parent,
TCPWrap::SocketType type) { TCPWrap::SocketType type) {
EscapableHandleScope handle_scope(env->isolate()); 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); CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
Local<Function> constructor = env->tcp_constructor_template()->GetFunction(); Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
CHECK_EQ(constructor.IsEmpty(), false); CHECK_EQ(constructor.IsEmpty(), false);
@ -292,7 +293,8 @@ void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
int err = uv_ip4_addr(*ip_address, port, &addr); int err = uv_ip4_addr(*ip_address, port, &addr);
if (err == 0) { 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 = ConnectWrap* req_wrap =
new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP); new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
err = uv_tcp_connect(req_wrap->req(), err = uv_tcp_connect(req_wrap->req(),
@ -328,7 +330,8 @@ void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
int err = uv_ip6_addr(*ip_address, port, &addr); int err = uv_ip6_addr(*ip_address, port, &addr);
if (err == 0) { 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 = ConnectWrap* req_wrap =
new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP); new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
err = uv_tcp_connect(req_wrap->req(), err = uv_tcp_connect(req_wrap->req(),

View File

@ -357,8 +357,12 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
node::Utf8Value address(env->isolate(), args[4]); node::Utf8Value address(env->isolate(), args[4]);
const bool have_callback = args[5]->IsTrue(); const bool have_callback = args[5]->IsTrue();
env->set_default_trigger_async_id(wrap->get_async_id()); SendWrap* req_wrap;
SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback); {
AsyncHooks::DefaultTriggerAsyncIdScope trigger_scope(
env, wrap->get_async_id());
req_wrap = new SendWrap(env, req_wrap_obj, have_callback);
}
size_t msg_size = 0; size_t msg_size = 0;
MaybeStackBuffer<uv_buf_t, 16> bufs(count); MaybeStackBuffer<uv_buf_t, 16> bufs(count);
@ -507,7 +511,9 @@ Local<Object> UDPWrap::Instantiate(Environment* env,
AsyncWrap* parent, AsyncWrap* parent,
UDPWrap::SocketType type) { UDPWrap::SocketType type) {
EscapableHandleScope scope(env->isolate()); 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. // If this assert fires then Initialize hasn't been called yet.
CHECK_EQ(env->udp_constructor_function().IsEmpty(), false); CHECK_EQ(env->udp_constructor_function().IsEmpty(), false);
Local<Object> instance = env->udp_constructor_function() Local<Object> instance = env->udp_constructor_function()