Browse Source

async_hooks: consistent internal naming

PR-URL: https://github.com/nodejs/node/pull/15569
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
canary-base
Andreas Madsen 7 years ago
parent
commit
3a69ef55e0
No known key found for this signature in database GPG Key ID: 2FEE61B3C9E40F20
  1. 66
      lib/async_hooks.js
  2. 17
      lib/internal/bootstrap_node.js
  3. 26
      lib/internal/process/next_tick.js
  4. 34
      lib/timers.js
  5. 6
      src/async-wrap-inl.h
  6. 134
      src/async-wrap.cc
  7. 14
      src/async-wrap.h
  8. 2
      src/connection_wrap.cc
  9. 114
      src/env-inl.h
  10. 4
      src/env.cc
  11. 53
      src/env.h
  12. 16
      src/node.cc
  13. 2
      src/node.h
  14. 2
      src/node_http_parser.cc
  15. 2
      src/pipe_wrap.cc
  16. 2
      src/stream_base-inl.h
  17. 8
      src/stream_base.cc
  18. 6
      src/tcp_wrap.cc
  19. 4
      src/udp_wrap.cc
  20. 6
      test/common/index.js
  21. 2
      test/parallel/test-async-wrap-destroyid.js

66
lib/async_hooks.js

@ -6,20 +6,21 @@ const errors = require('internal/errors');
* Environment::AsyncHooks::fields_[]. Each index tracks the number of active
* hooks for each type.
*
* async_uid_fields is a Float64Array wrapping the double array of
* async_id_fields is a Float64Array wrapping the double array of
* Environment::AsyncHooks::uid_fields_[]. Each index contains the ids for the
* various asynchronous states of the application. These are:
* kCurrentAsyncId: The async_id assigned to the resource responsible for the
* kExecutionAsyncId: The async_id assigned to the resource responsible for the
* current execution stack.
* kCurrentTriggerId: The trigger_async_id of the resource responsible for the
* current execution stack.
* kAsyncUidCntr: Incremental counter tracking the next assigned async_id.
* kInitTriggerId: Written immediately before a resource's constructor that
* sets the value of the init()'s triggerAsyncId. The order of retrieving
* the triggerAsyncId value is passing directly to the constructor -> value
* set in kInitTriggerId -> executionAsyncId of the current resource.
* kTriggerAsyncId: The trigger_async_id of the resource responsible for
* the current execution stack.
* kAsyncIdCounter: Incremental counter tracking the next assigned async_id.
* kInitTriggerAsyncId: Written immediately before a resource's constructor
* that sets the value of the init()'s triggerAsyncId. The order of
* retrieving the triggerAsyncId value is passing directly to the
* constructor -> value set in kInitTriggerAsyncId -> executionAsyncId of
* the current resource.
*/
const { async_hook_fields, async_uid_fields } = async_wrap;
const { async_hook_fields, async_id_fields } = async_wrap;
// Store the pair executionAsyncId and triggerAsyncId in a std::stack on
// Environment::AsyncHooks::ids_stack_ tracks the resource responsible for the
// current execution stack. This is unwound as each resource exits. In the case
@ -58,14 +59,14 @@ const active_hooks = {
// Each constant tracks how many callbacks there are for any given step of
// async execution. These are tracked so if the user didn't include callbacks
// for a given step, that step can bail out early.
const { kInit, kBefore, kAfter, kDestroy, kPromiseResolve, kTotals,
kCurrentAsyncId, kCurrentTriggerId, kAsyncUidCntr,
kInitTriggerId } = async_wrap.constants;
const { kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve,
kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
kInitTriggerAsyncId } = async_wrap.constants;
// Symbols used to store the respective ids on both AsyncResource instances and
// internal resources. They will also be assigned to arbitrary objects passed
// in by the user that take place of internally constructed objects.
const { async_id_symbol, trigger_id_symbol } = async_wrap;
const { async_id_symbol, trigger_async_id_symbol } = async_wrap;
// Used in AsyncHook and AsyncResource.
const init_symbol = Symbol('init');
@ -234,12 +235,12 @@ function createHook(fns) {
function executionAsyncId() {
return async_uid_fields[kCurrentAsyncId];
return async_id_fields[kExecutionAsyncId];
}
function triggerAsyncId() {
return async_uid_fields[kCurrentTriggerId];
return async_id_fields[kTriggerAsyncId];
}
@ -258,14 +259,16 @@ class AsyncResource {
triggerAsyncId);
}
this[async_id_symbol] = ++async_uid_fields[kAsyncUidCntr];
this[trigger_id_symbol] = triggerAsyncId;
this[async_id_symbol] = ++async_id_fields[kAsyncIdCounter];
this[trigger_async_id_symbol] = triggerAsyncId;
emitInitScript(this[async_id_symbol], type, this[trigger_id_symbol], this);
emitInitScript(
this[async_id_symbol], type, this[trigger_async_id_symbol], this
);
}
emitBefore() {
emitBeforeScript(this[async_id_symbol], this[trigger_id_symbol]);
emitBeforeScript(this[async_id_symbol], this[trigger_async_id_symbol]);
return this;
}
@ -284,7 +287,7 @@ class AsyncResource {
}
triggerAsyncId() {
return this[trigger_id_symbol];
return this[trigger_async_id_symbol];
}
}
@ -308,7 +311,7 @@ function runInAsyncIdScope(asyncId, cb) {
// counter increment first. Since it's done the same way in
// Environment::new_async_uid()
function newUid() {
return ++async_uid_fields[kAsyncUidCntr];
return ++async_id_fields[kAsyncIdCounter];
}
@ -316,20 +319,20 @@ function newUid() {
// the user to safeguard this call and make sure it's zero'd out when the
// constructor is complete.
function initTriggerId() {
var tId = async_uid_fields[kInitTriggerId];
var triggerAsyncId = async_id_fields[kInitTriggerAsyncId];
// Reset value after it's been called so the next constructor doesn't
// inherit it by accident.
async_uid_fields[kInitTriggerId] = 0;
if (tId <= 0)
tId = async_uid_fields[kCurrentAsyncId];
return tId;
async_id_fields[kInitTriggerAsyncId] = 0;
if (triggerAsyncId <= 0)
triggerAsyncId = async_id_fields[kExecutionAsyncId];
return triggerAsyncId;
}
function setInitTriggerId(triggerAsyncId) {
// CHECK(Number.isSafeInteger(triggerAsyncId))
// CHECK(triggerAsyncId > 0)
async_uid_fields[kInitTriggerId] = triggerAsyncId;
async_id_fields[kInitTriggerAsyncId] = triggerAsyncId;
}
@ -346,8 +349,9 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
if (triggerAsyncId === null) {
triggerAsyncId = initTriggerId();
} else {
// If a triggerAsyncId was passed, any kInitTriggerId still must be null'd.
async_uid_fields[kInitTriggerId] = 0;
// If a triggerAsyncId was passed, any kInitTriggerAsyncId still must be
// null'd.
async_id_fields[kInitTriggerAsyncId] = 0;
}
if (!Number.isSafeInteger(asyncId) || asyncId < -1) {
@ -446,7 +450,7 @@ function emitDestroyScript(asyncId) {
// Return early if there are no destroy callbacks, or invalid asyncId.
if (async_hook_fields[kDestroy] === 0 || asyncId <= 0)
return;
async_wrap.addIdToDestroyList(asyncId);
async_wrap.queueDestroyAsyncId(asyncId);
}

17
lib/internal/bootstrap_node.js

@ -354,17 +354,18 @@
function setupProcessFatal() {
const async_wrap = process.binding('async_wrap');
// Arrays containing hook flags and ids for async_hook calls.
const { async_hook_fields, async_uid_fields } = async_wrap;
const { async_hook_fields, async_id_fields } = async_wrap;
// Internal functions needed to manipulate the stack.
const { clearIdStack, asyncIdStackSize } = async_wrap;
const { kAfter, kCurrentAsyncId, kInitTriggerId } = async_wrap.constants;
const { clearAsyncIdStack, asyncIdStackSize } = async_wrap;
const { kAfter, kExecutionAsyncId,
kInitTriggerAsyncId } = async_wrap.constants;
process._fatalException = function(er) {
var caught;
// It's possible that kInitTriggerId was set for a constructor call that
// threw and was never cleared. So clear it now.
async_uid_fields[kInitTriggerId] = 0;
// It's possible that kInitTriggerAsyncId was set for a constructor call
// that threw and was never cleared. So clear it now.
async_id_fields[kInitTriggerAsyncId] = 0;
if (process.domain && process.domain._errorHandler)
caught = process.domain._errorHandler(er);
@ -392,11 +393,11 @@
if (async_hook_fields[kAfter] > 0) {
do {
NativeModule.require('async_hooks').emitAfter(
async_uid_fields[kCurrentAsyncId]);
async_id_fields[kExecutionAsyncId]);
} while (asyncIdStackSize() > 0);
// Or completely empty the id stack.
} else {
clearIdStack();
clearAsyncIdStack();
}
}

26
lib/internal/process/next_tick.js

@ -54,12 +54,12 @@ function setupNextTick() {
const emitPendingUnhandledRejections = promises.setup(scheduleMicrotasks);
const initTriggerId = async_hooks.initTriggerId;
// Two arrays that share state between C++ and JS.
const { async_hook_fields, async_uid_fields } = async_wrap;
const { async_hook_fields, async_id_fields } = async_wrap;
// Used to change the state of the async id stack.
const { emitInit, emitBefore, emitAfter, emitDestroy } = async_hooks;
// Grab the constants necessary for working with internal arrays.
const { kInit, kDestroy, kAsyncUidCntr } = async_wrap.constants;
const { async_id_symbol, trigger_id_symbol } = async_wrap;
const { kInit, kDestroy, kAsyncIdCounter } = async_wrap.constants;
const { async_id_symbol, trigger_async_id_symbol } = async_wrap;
var nextTickQueue = new NextTickQueue();
var microtasksScheduled = false;
@ -102,7 +102,7 @@ function setupNextTick() {
args: undefined,
domain: null,
[async_id_symbol]: 0,
[trigger_id_symbol]: 0
[trigger_async_id_symbol]: 0
};
function scheduleMicrotasks() {
if (microtasksScheduled)
@ -158,10 +158,10 @@ function setupNextTick() {
// CHECK(Number.isSafeInteger(tock[async_id_symbol]))
// CHECK(tock[async_id_symbol] > 0)
// CHECK(Number.isSafeInteger(tock[trigger_id_symbol]))
// CHECK(tock[trigger_id_symbol] > 0)
// CHECK(Number.isSafeInteger(tock[trigger_async_id_symbol]))
// CHECK(tock[trigger_async_id_symbol] > 0)
emitBefore(tock[async_id_symbol], tock[trigger_id_symbol]);
emitBefore(tock[async_id_symbol], tock[trigger_async_id_symbol]);
// emitDestroy() places the async_id_symbol into an asynchronous queue
// that calls the destroy callback in the future. It's called before
// calling tock.callback so destroy will be called even if the callback
@ -203,10 +203,10 @@ function setupNextTick() {
// CHECK(Number.isSafeInteger(tock[async_id_symbol]))
// CHECK(tock[async_id_symbol] > 0)
// CHECK(Number.isSafeInteger(tock[trigger_id_symbol]))
// CHECK(tock[trigger_id_symbol] > 0)
// CHECK(Number.isSafeInteger(tock[trigger_async_id_symbol]))
// CHECK(tock[trigger_async_id_symbol] > 0)
emitBefore(tock[async_id_symbol], tock[trigger_id_symbol]);
emitBefore(tock[async_id_symbol], tock[trigger_async_id_symbol]);
// TODO(trevnorris): See comment in _tickCallback() as to why this
// isn't a good solution.
if (async_hook_fields[kDestroy] > 0)
@ -236,7 +236,7 @@ function setupNextTick() {
this.args = args;
this.domain = process.domain || null;
this[async_id_symbol] = asyncId;
this[trigger_id_symbol] = triggerAsyncId;
this[trigger_async_id_symbol] = triggerAsyncId;
}
}
@ -261,7 +261,7 @@ function setupNextTick() {
args[i - 1] = arguments[i];
}
const asyncId = ++async_uid_fields[kAsyncUidCntr];
const asyncId = ++async_id_fields[kAsyncIdCounter];
const triggerAsyncId = initTriggerId();
const obj = new TickObject(callback, args, asyncId, triggerAsyncId);
nextTickQueue.push(obj);
@ -297,7 +297,7 @@ function setupNextTick() {
args[i - 2] = arguments[i];
}
const asyncId = ++async_uid_fields[kAsyncUidCntr];
const asyncId = ++async_id_fields[kAsyncIdCounter];
const obj = new TickObject(callback, args, asyncId, triggerAsyncId);
nextTickQueue.push(obj);
++tickInfo[kLength];

34
lib/timers.js

@ -34,14 +34,14 @@ const debug = util.debuglog('timer');
const kOnTimeout = TimerWrap.kOnTimeout | 0;
const initTriggerId = async_hooks.initTriggerId;
// Two arrays that share state between C++ and JS.
const { async_hook_fields, async_uid_fields } = async_wrap;
const { async_hook_fields, async_id_fields } = async_wrap;
// The needed emit*() functions.
const { emitInit, emitBefore, emitAfter, emitDestroy } = async_hooks;
// Grab the constants necessary for working with internal arrays.
const { kInit, kDestroy, kAsyncUidCntr } = async_wrap.constants;
const { kInit, kDestroy, kAsyncIdCounter } = async_wrap.constants;
// Symbols for storing async id state.
const async_id_symbol = Symbol('asyncId');
const trigger_id_symbol = Symbol('triggerAsyncId');
const trigger_async_id_symbol = Symbol('triggerAsyncId');
// Timeout values > TIMEOUT_MAX are set to 1.
const TIMEOUT_MAX = 2147483647; // 2^31-1
@ -169,10 +169,12 @@ function insert(item, unrefed) {
if (!item[async_id_symbol] || item._destroyed) {
item._destroyed = false;
item[async_id_symbol] = ++async_uid_fields[kAsyncUidCntr];
item[trigger_id_symbol] = initTriggerId();
item[async_id_symbol] = ++async_id_fields[kAsyncIdCounter];
item[trigger_async_id_symbol] = initTriggerId();
if (async_hook_fields[kInit] > 0)
emitInit(item[async_id_symbol], 'Timeout', item[trigger_id_symbol], item);
emitInit(
item[async_id_symbol], 'Timeout', item[trigger_async_id_symbol], item
);
}
L.append(list, item);
@ -291,7 +293,7 @@ function tryOnTimeout(timer, list) {
timer[async_id_symbol] : null;
var threw = true;
if (timerAsyncId !== null)
emitBefore(timerAsyncId, timer[trigger_id_symbol]);
emitBefore(timerAsyncId, timer[trigger_async_id_symbol]);
try {
ontimeout(timer);
threw = false;
@ -560,10 +562,12 @@ function Timeout(after, callback, args) {
this._timerArgs = args;
this._repeat = null;
this._destroyed = false;
this[async_id_symbol] = ++async_uid_fields[kAsyncUidCntr];
this[trigger_id_symbol] = initTriggerId();
this[async_id_symbol] = ++async_id_fields[kAsyncIdCounter];
this[trigger_async_id_symbol] = initTriggerId();
if (async_hook_fields[kInit] > 0)
emitInit(this[async_id_symbol], 'Timeout', this[trigger_id_symbol], this);
emitInit(
this[async_id_symbol], 'Timeout', this[trigger_async_id_symbol], this
);
}
@ -733,7 +737,7 @@ function processImmediate() {
// 4.7) what is in this smaller function.
function tryOnImmediate(immediate, oldTail) {
var threw = true;
emitBefore(immediate[async_id_symbol], immediate[trigger_id_symbol]);
emitBefore(immediate[async_id_symbol], immediate[trigger_async_id_symbol]);
try {
// make the actual call outside the try/finally to allow it to be optimized
runCallback(immediate);
@ -798,10 +802,12 @@ function Immediate() {
this._onImmediate = null;
this._destroyed = false;
this.domain = process.domain;
this[async_id_symbol] = ++async_uid_fields[kAsyncUidCntr];
this[trigger_id_symbol] = initTriggerId();
this[async_id_symbol] = ++async_id_fields[kAsyncIdCounter];
this[trigger_async_id_symbol] = initTriggerId();
if (async_hook_fields[kInit] > 0)
emitInit(this[async_id_symbol], 'Immediate', this[trigger_id_symbol], this);
emitInit(
this[async_id_symbol], 'Immediate', this[trigger_async_id_symbol], this
);
}
function setImmediate(callback, arg1, arg2, arg3) {

6
src/async-wrap-inl.h

@ -36,13 +36,13 @@ inline AsyncWrap::ProviderType AsyncWrap::provider_type() const {
}
inline double AsyncWrap::get_id() const {
inline double AsyncWrap::get_async_id() const {
return async_id_;
}
inline double AsyncWrap::get_trigger_id() const {
return trigger_id_;
inline double AsyncWrap::get_trigger_async_id() const {
return trigger_async_id_;
}

134
src/async-wrap.cc

@ -140,8 +140,8 @@ RetainedObjectInfo* WrapperInfo(uint16_t class_id, Local<Value> wrapper) {
// end RetainedAsyncInfo
static void DestroyIdsCb(uv_timer_t* handle) {
Environment* env = Environment::from_destroy_ids_timer_handle(handle);
static void DestroyAsyncIdsCallback(uv_timer_t* handle) {
Environment* env = Environment::from_destroy_async_ids_timer_handle(handle);
HandleScope handle_scope(env->isolate());
Context::Scope context_scope(env->context());
@ -150,15 +150,15 @@ static void DestroyIdsCb(uv_timer_t* handle) {
TryCatch try_catch(env->isolate());
do {
std::vector<double> destroy_ids_list;
destroy_ids_list.swap(*env->destroy_ids_list());
for (auto current_id : destroy_ids_list) {
std::vector<double> destroy_async_id_list;
destroy_async_id_list.swap(*env->destroy_async_id_list());
for (auto async_id : destroy_async_id_list) {
// Want each callback to be cleaned up after itself, instead of cleaning
// them all up after the while() loop completes.
HandleScope scope(env->isolate());
Local<Value> argv = Number::New(env->isolate(), current_id);
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
MaybeLocal<Value> ret = fn->Call(
env->context(), Undefined(env->isolate()), 1, &argv);
env->context(), Undefined(env->isolate()), 1, &async_id_value);
if (ret.IsEmpty()) {
ClearFatalExceptionHandlers(env);
@ -166,18 +166,19 @@ static void DestroyIdsCb(uv_timer_t* handle) {
UNREACHABLE();
}
}
} while (!env->destroy_ids_list()->empty());
} while (!env->destroy_async_id_list()->empty());
}
static void PushBackDestroyId(Environment* env, double id) {
static void PushBackDestroyAsyncId(Environment* env, double id) {
if (env->async_hooks()->fields()[AsyncHooks::kDestroy] == 0)
return;
if (env->destroy_ids_list()->empty())
uv_timer_start(env->destroy_ids_timer_handle(), DestroyIdsCb, 0, 0);
if (env->destroy_async_id_list()->empty())
uv_timer_start(env->destroy_async_ids_timer_handle(),
DestroyAsyncIdsCallback, 0, 0);
env->destroy_ids_list()->push_back(id);
env->destroy_async_id_list()->push_back(id);
}
@ -187,11 +188,11 @@ void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) {
if (async_hooks->fields()[AsyncHooks::kPromiseResolve] == 0)
return;
Local<Value> uid = Number::New(env->isolate(), async_id);
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
Local<Function> fn = env->async_hooks_promise_resolve_function();
TryCatch try_catch(env->isolate());
MaybeLocal<Value> ar = fn->Call(
env->context(), Undefined(env->isolate()), 1, &uid);
env->context(), Undefined(env->isolate()), 1, &async_id_value);
if (ar.IsEmpty()) {
ClearFatalExceptionHandlers(env);
FatalException(env->isolate(), try_catch);
@ -206,11 +207,11 @@ void AsyncWrap::EmitBefore(Environment* env, double async_id) {
if (async_hooks->fields()[AsyncHooks::kBefore] == 0)
return;
Local<Value> uid = Number::New(env->isolate(), async_id);
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
Local<Function> fn = env->async_hooks_before_function();
TryCatch try_catch(env->isolate());
MaybeLocal<Value> ar = fn->Call(
env->context(), Undefined(env->isolate()), 1, &uid);
env->context(), Undefined(env->isolate()), 1, &async_id_value);
if (ar.IsEmpty()) {
ClearFatalExceptionHandlers(env);
FatalException(env->isolate(), try_catch);
@ -227,11 +228,11 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
// If the user's callback failed then the after() hooks will be called at the
// end of _fatalException().
Local<Value> uid = Number::New(env->isolate(), async_id);
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
Local<Function> fn = env->async_hooks_after_function();
TryCatch try_catch(env->isolate());
MaybeLocal<Value> ar = fn->Call(
env->context(), Undefined(env->isolate()), 1, &uid);
env->context(), Undefined(env->isolate()), 1, &async_id_value);
if (ar.IsEmpty()) {
ClearFatalExceptionHandlers(env);
FatalException(env->isolate(), try_catch);
@ -248,7 +249,7 @@ class PromiseWrap : public AsyncWrap {
size_t self_size() const override { return sizeof(*this); }
static constexpr int kPromiseField = 1;
static constexpr int kParentIdField = 2;
static constexpr int kParentAsyncIdField = 2;
static constexpr int kInternalFieldCount = 3;
static PromiseWrap* New(Environment* env,
@ -257,7 +258,7 @@ class PromiseWrap : public AsyncWrap {
bool silent);
static void GetPromise(Local<String> property,
const PropertyCallbackInfo<Value>& info);
static void GetParentId(Local<String> property,
static void getParentAsyncId(Local<String> property,
const PropertyCallbackInfo<Value>& info);
};
@ -269,9 +270,9 @@ PromiseWrap* PromiseWrap::New(Environment* env,
->NewInstance(env->context()).ToLocalChecked();
object->SetInternalField(PromiseWrap::kPromiseField, promise);
if (parent_wrap != nullptr) {
object->SetInternalField(PromiseWrap::kParentIdField,
object->SetInternalField(PromiseWrap::kParentAsyncIdField,
Number::New(env->isolate(),
parent_wrap->get_id()));
parent_wrap->get_async_id()));
}
CHECK_EQ(promise->GetAlignedPointerFromInternalField(0), nullptr);
promise->SetInternalField(0, object);
@ -283,9 +284,10 @@ void PromiseWrap::GetPromise(Local<String> property,
info.GetReturnValue().Set(info.Holder()->GetInternalField(kPromiseField));
}
void PromiseWrap::GetParentId(Local<String> property,
void PromiseWrap::getParentAsyncId(Local<String> property,
const PropertyCallbackInfo<Value>& info) {
info.GetReturnValue().Set(info.Holder()->GetInternalField(kParentIdField));
info.GetReturnValue().Set(
info.Holder()->GetInternalField(kParentAsyncIdField));
}
static void PromiseHook(PromiseHookType type, Local<Promise> promise,
@ -317,8 +319,8 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
parent_wrap = PromiseWrap::New(env, parent_promise, nullptr, true);
}
// get id from parentWrap
double trigger_id = parent_wrap->get_id();
env->set_init_trigger_id(trigger_id);
double trigger_async_id = parent_wrap->get_async_id();
env->set_init_trigger_async_id(trigger_async_id);
}
wrap = PromiseWrap::New(env, promise, parent_wrap, silent);
@ -326,20 +328,21 @@ static void PromiseHook(PromiseHookType type, Local<Promise> promise,
CHECK_NE(wrap, nullptr);
if (type == PromiseHookType::kBefore) {
env->async_hooks()->push_ids(wrap->get_id(), wrap->get_trigger_id());
AsyncWrap::EmitBefore(wrap->env(), wrap->get_id());
env->async_hooks()->push_async_ids(
wrap->get_async_id(), wrap->get_trigger_async_id());
AsyncWrap::EmitBefore(wrap->env(), wrap->get_async_id());
} else if (type == PromiseHookType::kAfter) {
AsyncWrap::EmitAfter(wrap->env(), wrap->get_id());
if (env->current_async_id() == wrap->get_id()) {
AsyncWrap::EmitAfter(wrap->env(), wrap->get_async_id());
if (env->execution_async_id() == wrap->get_async_id()) {
// This condition might not be true if async_hooks was enabled during
// the promise callback execution.
// Popping it off the stack can be skipped in that case, because is is
// known that it would correspond to exactly one call with
// PromiseHookType::kBefore that was not witnessed by the PromiseHook.
env->async_hooks()->pop_ids(wrap->get_id());
env->async_hooks()->pop_async_id(wrap->get_async_id());
}
} else if (type == PromiseHookType::kResolve) {
AsyncWrap::EmitPromiseResolve(wrap->env(), wrap->get_id());
AsyncWrap::EmitPromiseResolve(wrap->env(), wrap->get_async_id());
}
}
@ -383,7 +386,7 @@ static void SetupHooks(const FunctionCallbackInfo<Value>& args) {
PromiseWrap::GetPromise);
promise_wrap_template->SetAccessor(
FIXED_ONE_BYTE_STRING(env->isolate(), "parentId"),
PromiseWrap::GetParentId);
PromiseWrap::getParentAsyncId);
env->set_promise_wrap_template(promise_wrap_template);
}
}
@ -411,24 +414,24 @@ void AsyncWrap::GetAsyncId(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap;
args.GetReturnValue().Set(-1);
ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder());
args.GetReturnValue().Set(wrap->get_id());
args.GetReturnValue().Set(wrap->get_async_id());
}
void AsyncWrap::PushAsyncIds(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
// No need for CHECK(IsNumber()) on args because if FromJust() doesn't fail
// then the checks in push_ids() and pop_ids() will.
// then the checks in push_async_ids() and pop_async_id() will.
double async_id = args[0]->NumberValue(env->context()).FromJust();
double trigger_id = args[1]->NumberValue(env->context()).FromJust();
env->async_hooks()->push_ids(async_id, trigger_id);
double trigger_async_id = args[1]->NumberValue(env->context()).FromJust();
env->async_hooks()->push_async_ids(async_id, trigger_async_id);
}
void AsyncWrap::PopAsyncIds(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
double async_id = args[0]->NumberValue(env->context()).FromJust();
args.GetReturnValue().Set(env->async_hooks()->pop_ids(async_id));
args.GetReturnValue().Set(env->async_hooks()->pop_async_id(async_id));
}
@ -439,9 +442,9 @@ void AsyncWrap::AsyncIdStackSize(const FunctionCallbackInfo<Value>& args) {
}
void AsyncWrap::ClearIdStack(const FunctionCallbackInfo<Value>& args) {
void AsyncWrap::ClearAsyncIdStack(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
env->async_hooks()->clear_id_stack();
env->async_hooks()->clear_async_id_stack();
}
@ -452,9 +455,9 @@ void AsyncWrap::AsyncReset(const FunctionCallbackInfo<Value>& args) {
}
void AsyncWrap::QueueDestroyId(const FunctionCallbackInfo<Value>& args) {
void AsyncWrap::QueueDestroyAsyncId(const FunctionCallbackInfo<Value>& args) {
CHECK(args[0]->IsNumber());
PushBackDestroyId(Environment::GetCurrent(args), args[0]->NumberValue());
PushBackDestroyAsyncId(Environment::GetCurrent(args), args[0]->NumberValue());
}
void AsyncWrap::AddWrapMethods(Environment* env,
@ -476,8 +479,8 @@ void AsyncWrap::Initialize(Local<Object> target,
env->SetMethod(target, "pushAsyncIds", PushAsyncIds);
env->SetMethod(target, "popAsyncIds", PopAsyncIds);
env->SetMethod(target, "asyncIdStackSize", AsyncIdStackSize);
env->SetMethod(target, "clearIdStack", ClearIdStack);
env->SetMethod(target, "addIdToDestroyList", QueueDestroyId);
env->SetMethod(target, "clearAsyncIdStack", ClearAsyncIdStack);
env->SetMethod(target, "queueDestroyAsyncId", QueueDestroyAsyncId);
env->SetMethod(target, "enablePromiseHook", EnablePromiseHook);
env->SetMethod(target, "disablePromiseHook", DisablePromiseHook);
@ -504,12 +507,12 @@ void AsyncWrap::Initialize(Local<Object> target,
//
// kAsyncUid: Maintains the state of the next unique id to be assigned.
//
// kInitTriggerId: Write the id of the resource responsible for a handle's
// creation just before calling the new handle's constructor. After the new
// handle is constructed kInitTriggerId is set back to 0.
// kInitTriggerAsyncId: Write the id of the resource responsible for a
// handle's creation just before calling the new handle's constructor.
// After the new handle is constructed kInitTriggerAsyncId is set back to 0.
FORCE_SET_TARGET_FIELD(target,
"async_uid_fields",
env->async_hooks()->uid_fields().GetJSArray());
"async_id_fields",
env->async_hooks()->async_id_fields().GetJSArray());
Local<Object> constants = Object::New(isolate);
#define SET_HOOKS_CONSTANT(name) \
@ -522,10 +525,10 @@ void AsyncWrap::Initialize(Local<Object> target,
SET_HOOKS_CONSTANT(kDestroy);
SET_HOOKS_CONSTANT(kPromiseResolve);
SET_HOOKS_CONSTANT(kTotals);
SET_HOOKS_CONSTANT(kCurrentAsyncId);
SET_HOOKS_CONSTANT(kCurrentTriggerId);
SET_HOOKS_CONSTANT(kAsyncUidCntr);
SET_HOOKS_CONSTANT(kInitTriggerId);
SET_HOOKS_CONSTANT(kExecutionAsyncId);
SET_HOOKS_CONSTANT(kTriggerAsyncId);
SET_HOOKS_CONSTANT(kAsyncIdCounter);
SET_HOOKS_CONSTANT(kInitTriggerAsyncId);
#undef SET_HOOKS_CONSTANT
FORCE_SET_TARGET_FIELD(target, "constants", constants);
@ -545,8 +548,8 @@ void AsyncWrap::Initialize(Local<Object> target,
Symbol::New(isolate, FIXED_ONE_BYTE_STRING(isolate, "asyncId")));
FORCE_SET_TARGET_FIELD(
target,
"trigger_id_symbol",
Symbol::New(isolate, FIXED_ONE_BYTE_STRING(isolate, "triggerId")));
"trigger_async_id_symbol",
Symbol::New(isolate, FIXED_ONE_BYTE_STRING(isolate, "triggerAsyncId")));
#undef FORCE_SET_TARGET_FIELD
@ -586,7 +589,7 @@ AsyncWrap::AsyncWrap(Environment* env,
AsyncWrap::~AsyncWrap() {
PushBackDestroyId(env(), get_id());
PushBackDestroyAsyncId(env(), get_async_id());
}
@ -595,13 +598,13 @@ AsyncWrap::~AsyncWrap() {
// the resource is pulled out of the pool and put back into use.
void AsyncWrap::AsyncReset(bool silent) {
async_id_ = env()->new_async_id();
trigger_id_ = env()->get_init_trigger_id();
trigger_async_id_ = env()->get_init_trigger_async_id();
if (silent) return;
EmitAsyncInit(env(), object(),
env()->async_hooks()->provider_string(provider_type()),
async_id_, trigger_id_);
async_id_, trigger_async_id_);
}
@ -609,7 +612,7 @@ void AsyncWrap::EmitAsyncInit(Environment* env,
Local<Object> object,
Local<String> type,
double async_id,
double trigger_id) {
double trigger_async_id) {
CHECK(!object.IsEmpty());
CHECK(!type.IsEmpty());
AsyncHooks* async_hooks = env->async_hooks();
@ -625,7 +628,7 @@ void AsyncWrap::EmitAsyncInit(Environment* env,
Local<Value> argv[] = {
Number::New(env->isolate(), async_id),
type,
Number::New(env->isolate(), trigger_id),
Number::New(env->isolate(), trigger_async_id),
object,
};
@ -643,7 +646,7 @@ void AsyncWrap::EmitAsyncInit(Environment* env,
MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
int argc,
Local<Value>* argv) {
async_context context { get_id(), get_trigger_id() };
async_context context { get_async_id(), get_trigger_async_id() };
return InternalMakeCallback(env(), object(), cb, argc, argv, context);
}
@ -652,12 +655,12 @@ MaybeLocal<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->current_async_id();
return Environment::GetCurrent(isolate)->execution_async_id();
}
async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) {
return Environment::GetCurrent(isolate)->trigger_id();
return Environment::GetCurrent(isolate)->trigger_async_id();
}
@ -679,7 +682,7 @@ async_context EmitAsyncInit(Isolate* isolate,
// Initialize async context struct
if (trigger_async_id == -1)
trigger_async_id = env->get_init_trigger_id();
trigger_async_id = env->get_init_trigger_async_id();
async_context context = {
env->new_async_id(), // async_id_
@ -694,7 +697,8 @@ async_context EmitAsyncInit(Isolate* isolate,
}
void EmitAsyncDestroy(Isolate* isolate, async_context asyncContext) {
PushBackDestroyId(Environment::GetCurrent(isolate), asyncContext.async_id);
PushBackDestroyAsyncId(Environment::GetCurrent(isolate),
asyncContext.async_id);
}
} // namespace node

14
src/async-wrap.h

@ -111,15 +111,17 @@ class AsyncWrap : public BaseObject {
static void PushAsyncIds(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PopAsyncIds(const v8::FunctionCallbackInfo<v8::Value>& args);
static void AsyncIdStackSize(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ClearIdStack(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ClearAsyncIdStack(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void AsyncReset(const v8::FunctionCallbackInfo<v8::Value>& args);
static void QueueDestroyId(const v8::FunctionCallbackInfo<v8::Value>& args);
static void QueueDestroyAsyncId(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void EmitAsyncInit(Environment* env,
v8::Local<v8::Object> object,
v8::Local<v8::String> type,
double id,
double trigger_id);
double trigger_async_id);
static void EmitBefore(Environment* env, double id);
static void EmitAfter(Environment* env, double id);
@ -127,9 +129,9 @@ class AsyncWrap : public BaseObject {
inline ProviderType provider_type() const;
inline double get_id() const;
inline double get_async_id() const;
inline double get_trigger_id() const;
inline double get_trigger_async_id() const;
void AsyncReset(bool silent = false);
@ -152,7 +154,7 @@ class AsyncWrap : public BaseObject {
const ProviderType provider_type_;
// Because the values may be Reset(), cannot be made const.
double async_id_;
double trigger_id_;
double trigger_async_id_;
};
void LoadAsyncWrapperInfo(Environment* env);

2
src/connection_wrap.cc

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

114
src/env-inl.h

@ -85,12 +85,12 @@ inline uint32_t* IsolateData::zero_fill_field() const {
inline Environment::AsyncHooks::AsyncHooks(v8::Isolate* isolate)
: isolate_(isolate),
fields_(isolate, kFieldsCount),
uid_fields_(isolate, kUidFieldsCount) {
async_id_fields_(isolate, kUidFieldsCount) {
v8::HandleScope handle_scope(isolate_);
// kAsyncUidCntr should start at 1 because that'll be the id the execution
// kAsyncIdCounter should start at 1 because that'll be the id the execution
// context during bootstrap (code that runs before entering uv_run()).
uid_fields_[AsyncHooks::kAsyncUidCntr] = 1;
async_id_fields_[AsyncHooks::kAsyncIdCounter] = 1;
// Create all the provider strings that will be passed to JS. Place them in
// an array so the array index matches the PROVIDER id offset. This way the
@ -117,11 +117,11 @@ inline int Environment::AsyncHooks::fields_count() const {
}
inline AliasedBuffer<double, v8::Float64Array>&
Environment::AsyncHooks::uid_fields() {
return uid_fields_;
Environment::AsyncHooks::async_id_fields() {
return async_id_fields_;
}
inline int Environment::AsyncHooks::uid_fields_count() const {
inline int Environment::AsyncHooks::async_id_fields_count() const {
return kUidFieldsCount;
}
@ -129,29 +129,29 @@ inline v8::Local<v8::String> Environment::AsyncHooks::provider_string(int idx) {
return providers_[idx].Get(isolate_);
}
inline void Environment::AsyncHooks::push_ids(double async_id,
double trigger_id) {
inline void Environment::AsyncHooks::push_async_ids(double async_id,
double trigger_async_id) {
CHECK_GE(async_id, -1);
CHECK_GE(trigger_id, -1);
CHECK_GE(trigger_async_id, -1);
ids_stack_.push({ uid_fields_[kCurrentAsyncId],
uid_fields_[kCurrentTriggerId] });
uid_fields_[kCurrentAsyncId] = async_id;
uid_fields_[kCurrentTriggerId] = trigger_id;
async_ids_stack_.push({ async_id_fields_[kExecutionAsyncId],
async_id_fields_[kTriggerAsyncId] });
async_id_fields_[kExecutionAsyncId] = async_id;
async_id_fields_[kTriggerAsyncId] = trigger_async_id;
}
inline bool Environment::AsyncHooks::pop_ids(double async_id) {
inline bool Environment::AsyncHooks::pop_async_id(double async_id) {
// In case of an exception then this may have already been reset, if the
// stack was multiple MakeCallback()'s deep.
if (ids_stack_.empty()) return false;
if (async_ids_stack_.empty()) return false;
// Ask for the async_id to be restored as a sanity check that the stack
// hasn't been corrupted.
if (uid_fields_[kCurrentAsyncId] != async_id) {
if (async_id_fields_[kExecutionAsyncId] != async_id) {
fprintf(stderr,
"Error: async hook stack has become corrupted ("
"actual: %.f, expected: %.f)\n",
uid_fields_.GetValue(kCurrentAsyncId),
async_id_fields_.GetValue(kExecutionAsyncId),
async_id);
Environment* env = Environment::GetCurrent(isolate_);
DumpBacktrace(stderr);
@ -163,35 +163,37 @@ inline bool Environment::AsyncHooks::pop_ids(double async_id) {
ABORT_NO_BACKTRACE();
}
auto ids = ids_stack_.top();
ids_stack_.pop();
uid_fields_[kCurrentAsyncId] = ids.async_id;
uid_fields_[kCurrentTriggerId] = ids.trigger_id;
return !ids_stack_.empty();
auto async_ids = async_ids_stack_.top();
async_ids_stack_.pop();
async_id_fields_[kExecutionAsyncId] = async_ids.async_id;
async_id_fields_[kTriggerAsyncId] = async_ids.trigger_async_id;
return !async_ids_stack_.empty();
}
inline size_t Environment::AsyncHooks::stack_size() {
return ids_stack_.size();
return async_ids_stack_.size();
}
inline void Environment::AsyncHooks::clear_id_stack() {
while (!ids_stack_.empty())
ids_stack_.pop();
uid_fields_[kCurrentAsyncId] = 0;
uid_fields_[kCurrentTriggerId] = 0;
inline void Environment::AsyncHooks::clear_async_id_stack() {
while (!async_ids_stack_.empty())
async_ids_stack_.pop();
async_id_fields_[kExecutionAsyncId] = 0;
async_id_fields_[kTriggerAsyncId] = 0;
}
inline Environment::AsyncHooks::InitScope::InitScope(
Environment* env, double init_trigger_id)
Environment* env, double init_trigger_async_id)
: env_(env),
uid_fields_ref_(env->async_hooks()->uid_fields()) {
CHECK_GE(init_trigger_id, -1);
env->async_hooks()->push_ids(uid_fields_ref_[AsyncHooks::kCurrentAsyncId],
init_trigger_id);
async_id_fields_ref_(env->async_hooks()->async_id_fields()) {
CHECK_GE(init_trigger_async_id, -1);
env->async_hooks()->push_async_ids(
async_id_fields_ref_[AsyncHooks::kExecutionAsyncId],
init_trigger_async_id);
}
inline Environment::AsyncHooks::InitScope::~InitScope() {
env_->async_hooks()->pop_ids(uid_fields_ref_[AsyncHooks::kCurrentAsyncId]);
env_->async_hooks()->pop_async_id(
async_id_fields_ref_[AsyncHooks::kExecutionAsyncId]);
}
inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env)
@ -306,7 +308,7 @@ inline Environment::Environment(IsolateData* isolate_data,
AssignToContext(context);
destroy_ids_list_.reserve(512);
destroy_async_id_list_.reserve(512);
performance_state_ = Calloc<performance::performance_state>(1);
performance_state_->milestones[
performance::NODE_PERFORMANCE_MILESTONE_ENVIRONMENT] =
@ -358,13 +360,13 @@ inline uv_idle_t* Environment::immediate_idle_handle() {
return &immediate_idle_handle_;
}
inline Environment* Environment::from_destroy_ids_timer_handle(
inline Environment* Environment::from_destroy_async_ids_timer_handle(
uv_timer_t* handle) {
return ContainerOf(&Environment::destroy_ids_timer_handle_, handle);
return ContainerOf(&Environment::destroy_async_ids_timer_handle_, handle);
}
inline uv_timer_t* Environment::destroy_ids_timer_handle() {
return &destroy_ids_timer_handle_;
inline uv_timer_t* Environment::destroy_async_ids_timer_handle() {
return &destroy_async_ids_timer_handle_;
}
inline void Environment::RegisterHandleCleanup(uv_handle_t* handle,
@ -425,35 +427,35 @@ inline void Environment::set_abort_on_uncaught_exception(bool value) {
abort_on_uncaught_exception_ = value;
}
inline std::vector<double>* Environment::destroy_ids_list() {
return &destroy_ids_list_;
inline std::vector<double>* Environment::destroy_async_id_list() {
return &destroy_async_id_list_;
}
inline double Environment::new_async_id() {
async_hooks()->uid_fields()[AsyncHooks::kAsyncUidCntr] =
async_hooks()->uid_fields()[AsyncHooks::kAsyncUidCntr] + 1;
return async_hooks()->uid_fields()[AsyncHooks::kAsyncUidCntr];
async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] =
async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter] + 1;
return async_hooks()->async_id_fields()[AsyncHooks::kAsyncIdCounter];
}
inline double Environment::current_async_id() {
return async_hooks()->uid_fields()[AsyncHooks::kCurrentAsyncId];
inline double Environment::execution_async_id() {
return async_hooks()->async_id_fields()[AsyncHooks::kExecutionAsyncId];
}
inline double Environment::trigger_id() {
return async_hooks()->uid_fields()[AsyncHooks::kCurrentTriggerId];
inline double Environment::trigger_async_id() {
return async_hooks()->async_id_fields()[AsyncHooks::kTriggerAsyncId];
}
inline double Environment::get_init_trigger_id() {
AliasedBuffer<double, v8::Float64Array>& uid_fields =
async_hooks()->uid_fields();
double tid = uid_fields[AsyncHooks::kInitTriggerId];
uid_fields[AsyncHooks::kInitTriggerId] = 0;
if (tid <= 0) tid = current_async_id();
inline double Environment::get_init_trigger_async_id() {
AliasedBuffer<double, v8::Float64Array>& async_id_fields =
async_hooks()->async_id_fields();
double tid = async_id_fields[AsyncHooks::kInitTriggerAsyncId];
async_id_fields[AsyncHooks::kInitTriggerAsyncId] = 0;
if (tid <= 0) tid = execution_async_id();
return tid;
}
inline void Environment::set_init_trigger_id(const double id) {
async_hooks()->uid_fields()[AsyncHooks::kInitTriggerId] = id;
inline void Environment::set_init_trigger_async_id(const double id) {
async_hooks()->async_id_fields()[AsyncHooks::kInitTriggerAsyncId] = id;
}
inline double* Environment::heap_statistics_buffer() const {

4
src/env.cc

@ -48,7 +48,7 @@ void Environment::Start(int argc,
uv_unref(reinterpret_cast<uv_handle_t*>(&idle_prepare_handle_));
uv_unref(reinterpret_cast<uv_handle_t*>(&idle_check_handle_));
uv_timer_init(event_loop(), destroy_ids_timer_handle());
uv_timer_init(event_loop(), destroy_async_ids_timer_handle());
auto close_and_finish = [](Environment* env, uv_handle_t* handle, void* arg) {
handle->data = env;
@ -75,7 +75,7 @@ void Environment::Start(int argc,
close_and_finish,
nullptr);
RegisterHandleCleanup(
reinterpret_cast<uv_handle_t*>(&destroy_ids_timer_handle_),
reinterpret_cast<uv_handle_t*>(&destroy_async_ids_timer_handle_),
close_and_finish,
nullptr);

53
src/env.h

@ -332,7 +332,7 @@ class Environment;
struct node_async_ids {
double async_id;
double trigger_id;
double trigger_async_id;
};
class IsolateData {
@ -388,10 +388,10 @@ class Environment {
};
enum UidFields {
kCurrentAsyncId,
kCurrentTriggerId,
kAsyncUidCntr,
kInitTriggerId,
kExecutionAsyncId,
kTriggerAsyncId,
kAsyncIdCounter,
kInitTriggerAsyncId,
kUidFieldsCount,
};
@ -400,28 +400,28 @@ class Environment {
inline AliasedBuffer<uint32_t, v8::Uint32Array>& fields();
inline int fields_count() const;
inline AliasedBuffer<double, v8::Float64Array>& uid_fields();
inline int uid_fields_count() const;
inline AliasedBuffer<double, v8::Float64Array>& async_id_fields();
inline int async_id_fields_count() const;
inline v8::Local<v8::String> provider_string(int idx);
inline void push_ids(double async_id, double trigger_id);
inline bool pop_ids(double async_id);
inline void push_async_ids(double async_id, double trigger_async_id);
inline bool pop_async_id(double async_id);
inline size_t stack_size();
inline void clear_id_stack(); // Used in fatal exceptions.
inline void clear_async_id_stack(); // Used in fatal exceptions.
// Used to propagate the trigger_id to the constructor of any newly created
// resources using RAII. Instead of needing to pass the trigger_id along
// with other constructor arguments.
// 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 {
public:
InitScope() = delete;
explicit InitScope(Environment* env, double init_trigger_id);
explicit InitScope(Environment* env, double init_trigger_async_id);
~InitScope();
private:
Environment* env_;
AliasedBuffer<double, v8::Float64Array> uid_fields_ref_;
AliasedBuffer<double, v8::Float64Array> async_id_fields_ref_;
DISALLOW_COPY_AND_ASSIGN(InitScope);
};
@ -434,12 +434,12 @@ class Environment {
// Used by provider_string().
v8::Isolate* isolate_;
// Stores the ids of the current execution context stack.
std::stack<struct node_async_ids> ids_stack_;
std::stack<struct node_async_ids> async_ids_stack_;
// Attached to a Uint32Array that tracks the number of active hooks for
// each type.
AliasedBuffer<uint32_t, v8::Uint32Array> fields_;
// Attached to a Float64Array that tracks the state of async resources.
AliasedBuffer<double, v8::Float64Array> uid_fields_;
AliasedBuffer<double, v8::Float64Array> async_id_fields_;
DISALLOW_COPY_AND_ASSIGN(AsyncHooks);
};
@ -549,10 +549,11 @@ class Environment {
inline uint32_t watched_providers() const;
static inline Environment* from_immediate_check_handle(uv_check_t* handle);
static inline Environment* from_destroy_ids_timer_handle(uv_timer_t* handle);
static inline Environment* from_destroy_async_ids_timer_handle(
uv_timer_t* handle);
inline uv_check_t* immediate_check_handle();
inline uv_idle_t* immediate_idle_handle();
inline uv_timer_t* destroy_ids_timer_handle();
inline uv_timer_t* destroy_async_ids_timer_handle();
// Register clean-up cb to be called on environment destruction.
inline void RegisterHandleCleanup(uv_handle_t* handle,
@ -581,13 +582,13 @@ class Environment {
// The necessary API for async_hooks.
inline double new_async_id();
inline double current_async_id();
inline double trigger_id();
inline double get_init_trigger_id();
inline void set_init_trigger_id(const double id);
inline double execution_async_id();
inline double trigger_async_id();
inline double get_init_trigger_async_id();
inline void set_init_trigger_async_id(const double id);
// List of id's that have been destroyed and need the destroy() cb called.
inline std::vector<double>* destroy_ids_list();
inline std::vector<double>* destroy_async_id_list();
std::unordered_multimap<int, loader::ModuleWrap*> module_map;
@ -686,7 +687,7 @@ class Environment {
IsolateData* const isolate_data_;
uv_check_t immediate_check_handle_;
uv_idle_t immediate_idle_handle_;
uv_timer_t destroy_ids_timer_handle_;
uv_timer_t destroy_async_ids_timer_handle_;
uv_prepare_t idle_prepare_handle_;
uv_check_t idle_check_handle_;
@ -700,7 +701,7 @@ class Environment {
bool abort_on_uncaught_exception_;
bool emit_napi_warning_;
size_t makecallback_cntr_;
std::vector<double> destroy_ids_list_;
std::vector<double> destroy_async_id_list_;
performance::performance_state* performance_state_ = nullptr;
std::map<std::string, uint64_t> performance_marks_;

16
src/node.cc

@ -1381,7 +1381,7 @@ InternalCallbackScope::InternalCallbackScope(Environment* env,
AsyncWrap::EmitBefore(env, asyncContext.async_id);
}
env->async_hooks()->push_ids(async_context_.async_id,
env->async_hooks()->push_async_ids(async_context_.async_id,
async_context_.trigger_async_id);
pushed_ids_ = true;
}
@ -1396,7 +1396,7 @@ void InternalCallbackScope::Close() {
HandleScope handle_scope(env_->isolate());
if (pushed_ids_)
env_->async_hooks()->pop_ids(async_context_.async_id);
env_->async_hooks()->pop_async_id(async_context_.async_id);
if (failed_) return;
@ -1420,8 +1420,8 @@ void InternalCallbackScope::Close() {
// Make sure the stack unwound properly. If there are nested MakeCallback's
// then it should return early and not reach this code.
CHECK_EQ(env_->current_async_id(), 0);
CHECK_EQ(env_->trigger_id(), 0);
CHECK_EQ(env_->execution_async_id(), 0);
CHECK_EQ(env_->trigger_async_id(), 0);
Local<Object> process = env_->process_object();
@ -1430,8 +1430,8 @@ void InternalCallbackScope::Close() {
return;
}
CHECK_EQ(env_->current_async_id(), 0);
CHECK_EQ(env_->trigger_id(), 0);
CHECK_EQ(env_->execution_async_id(), 0);
CHECK_EQ(env_->trigger_async_id(), 0);
if (env_->tick_callback_function()->Call(process, 0, nullptr).IsEmpty()) {
failed_ = true;
@ -4695,9 +4695,9 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data,
{
Environment::AsyncCallbackScope callback_scope(&env);
env.async_hooks()->push_ids(1, 0);
env.async_hooks()->push_async_ids(1, 0);
LoadEnvironment(&env);
env.async_hooks()->pop_ids(1);
env.async_hooks()->pop_async_id(1);
}
env.set_trace_sync_io(trace_sync_io);

2
src/node.h

@ -556,7 +556,7 @@ NODE_EXTERN async_id AsyncHooksGetTriggerAsyncId(v8::Isolate* isolate);
/* If the native API doesn't inherit from the helper class then the callbacks
* must be triggered manually. This triggers the init() callback. The return
* value is the uid assigned to the resource.
* value is the async id assigned to the resource.
*
* The `trigger_async_id` parameter should correspond to the resource which is
* creating the new resource, which will usually be the return value of

2
src/node_http_parser.cc

@ -479,7 +479,7 @@ class Parser : public AsyncWrap {
ASSIGN_OR_RETURN_UNWRAP(&parser, args.Holder());
// Should always be called from the same context.
CHECK_EQ(env, parser->env());
// The parser is being reused. Reset the uid and call init() callbacks.
// The parser is being reused. Reset the async id and call init() callbacks.
parser->AsyncReset();
parser->Init(type);
}

2
src/pipe_wrap.cc

@ -52,7 +52,7 @@ using AsyncHooks = Environment::AsyncHooks;
Local<Object> PipeWrap::Instantiate(Environment* env, AsyncWrap* parent) {
EscapableHandleScope handle_scope(env->isolate());
AsyncHooks::InitScope init_scope(env, parent->get_id());
AsyncHooks::InitScope init_scope(env, parent->get_async_id());
CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
CHECK_EQ(false, constructor.IsEmpty());

2
src/stream_base-inl.h

@ -136,7 +136,7 @@ void StreamBase::JSMethod(const FunctionCallbackInfo<Value>& args) {
if (!wrap->IsAlive())
return args.GetReturnValue().Set(UV_EINVAL);
AsyncHooks::InitScope init_scope(handle->env(), handle->get_id());
AsyncHooks::InitScope init_scope(handle->env(), handle->get_async_id());
args.GetReturnValue().Set((wrap->*Method)(args));
}

8
src/stream_base.cc

@ -55,7 +55,7 @@ int StreamBase::Shutdown(const FunctionCallbackInfo<Value>& args) {
AsyncWrap* wrap = GetAsyncWrap();
CHECK_NE(wrap, nullptr);
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
ShutdownWrap* req_wrap = new ShutdownWrap(env,
req_wrap_obj,
this,
@ -160,7 +160,7 @@ int StreamBase::Writev(const FunctionCallbackInfo<Value>& args) {
wrap = GetAsyncWrap();
CHECK_NE(wrap, nullptr);
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite, storage_size);
offset = 0;
@ -249,7 +249,7 @@ int StreamBase::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
wrap = GetAsyncWrap();
if (wrap != nullptr)
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
// Allocate, or write rest
req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite);
@ -334,7 +334,7 @@ int StreamBase::WriteString(const FunctionCallbackInfo<Value>& args) {
wrap = GetAsyncWrap();
if (wrap != nullptr)
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
req_wrap = WriteWrap::New(env, req_wrap_obj, this, AfterWrite, storage_size);
data = req_wrap->Extra();

6
src/tcp_wrap.cc

@ -55,7 +55,7 @@ using AsyncHooks = Environment::AsyncHooks;
Local<Object> TCPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
EscapableHandleScope handle_scope(env->isolate());
AsyncHooks::InitScope init_scope(env, parent->get_id());
AsyncHooks::InitScope init_scope(env, parent->get_async_id());
CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
CHECK_EQ(constructor.IsEmpty(), false);
@ -268,7 +268,7 @@ void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
int err = uv_ip4_addr(*ip_address, port, &addr);
if (err == 0) {
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
ConnectWrap* req_wrap =
new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
err = uv_tcp_connect(req_wrap->req(),
@ -304,7 +304,7 @@ void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
int err = uv_ip6_addr(*ip_address, port, &addr);
if (err == 0) {
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
ConnectWrap* req_wrap =
new ConnectWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_TCPCONNECTWRAP);
err = uv_tcp_connect(req_wrap->req(),

4
src/udp_wrap.cc

@ -350,7 +350,7 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
node::Utf8Value address(env->isolate(), args[4]);
const bool have_callback = args[5]->IsTrue();
env->set_init_trigger_id(wrap->get_id());
env->set_init_trigger_async_id(wrap->get_async_id());
SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback);
size_t msg_size = 0;
@ -498,7 +498,7 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
Local<Object> UDPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
EscapableHandleScope scope(env->isolate());
AsyncHooks::InitScope init_scope(env, parent->get_id());
AsyncHooks::InitScope init_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<Object> instance = env->udp_constructor_function()

6
test/common/index.js

@ -74,15 +74,15 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) {
util.inspect(initHandles[k]);
});
const _addIdToDestroyList = async_wrap.addIdToDestroyList;
async_wrap.addIdToDestroyList = function addIdToDestroyList(id) {
const _queueDestroyAsyncId = async_wrap.queueDestroyAsyncId;
async_wrap.queueDestroyAsyncId = function queueDestroyAsyncId(id) {
if (destroyListList[id] !== undefined) {
process._rawDebug(destroyListList[id]);
process._rawDebug();
throw new Error(`same id added twice (${id})`);
}
destroyListList[id] = new Error().stack;
_addIdToDestroyList(id);
_queueDestroyAsyncId(id);
};
require('async_hooks').createHook({

2
test/parallel/test-async-wrap-destroyid.js

@ -32,6 +32,6 @@ hooks = async_hooks.createHook({
if (n <= 0) return;
test_id = (Math.random() * 1e9) >>> 0;
async_wrap.addIdToDestroyList(test_id);
async_wrap.queueDestroyAsyncId(test_id);
setImmediate(common.mustCall(runner), n - 1);
})(RUNS);

Loading…
Cancel
Save