Skip to content
This repository has been archived by the owner on Aug 31, 2018. It is now read-only.

Apply some async hooks changes from upstream #87

Merged
merged 3 commits into from
Sep 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 35 additions & 31 deletions lib/async_hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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');
Expand Down Expand Up @@ -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];
}


Expand All @@ -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;
}

Expand All @@ -284,7 +287,7 @@ class AsyncResource {
}

triggerAsyncId() {
return this[trigger_id_symbol];
return this[trigger_async_id_symbol];
}
}

Expand All @@ -308,28 +311,28 @@ 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];
}


// Return the triggerAsyncId meant for the constructor calling it. It's up to
// 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;
}


Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}


Expand Down
17 changes: 9 additions & 8 deletions lib/internal/bootstrap_node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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();
}
}

Expand Down
26 changes: 13 additions & 13 deletions lib/internal/process/next_tick.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
}

Expand All @@ -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);
Expand Down Expand Up @@ -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];
Expand Down
34 changes: 20 additions & 14 deletions lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -577,10 +579,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
);
}


Expand Down Expand Up @@ -750,7 +754,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);
Expand Down Expand Up @@ -815,10 +819,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) {
Expand Down
6 changes: 3 additions & 3 deletions src/async-wrap-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_;
}


Expand Down
Loading