src: remove Async Listener
Async Listener was the name of the user-facing JS API, and is being completely removed. Instead low level hooks directly into the mechanism that AL used will be introduced in a future commit. PR-URL: https://github.com/joyent/node/pull/8110 Signed-off-by: Trevor Norris <trev.norris@gmail.com> Reviewed-by: Fedor Indutny <fedor@indutny.com> Reviewed-by: Alexis Campailla <alexis@janeasystems.com> Reviewed-by: Julien Gilli <julien.gilli@joyent.com>
This commit is contained in:
parent
4d94658918
commit
0d60ab3efe
@ -5,16 +5,6 @@
|
||||
The tracing module is designed for instrumenting your Node application. It is
|
||||
not meant for general purpose use.
|
||||
|
||||
***Be very careful with callbacks used in conjunction with this module***
|
||||
|
||||
Many of these callbacks interact directly with asynchronous subsystems in a
|
||||
synchronous fashion. That is to say, you may be in a callback where a call to
|
||||
`console.log()` could result in an infinite recursive loop. Also of note, many
|
||||
of these callbacks are in hot execution code paths. That is to say your
|
||||
callbacks are executed quite often in the normal operation of Node, so be wary
|
||||
of doing CPU bound or synchronous workloads in these functions. Consider a ring
|
||||
buffer and a timer to defer processing.
|
||||
|
||||
`require('tracing')` to use this module.
|
||||
|
||||
## v8
|
||||
@ -73,216 +63,4 @@ v8.setFlagsFromString('--trace_gc');
|
||||
setTimeout(function() { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
|
||||
```
|
||||
|
||||
|
||||
# Async Listeners
|
||||
|
||||
The `AsyncListener` API is the JavaScript interface for the `AsyncWrap`
|
||||
class which allows developers to be notified about key events in the
|
||||
lifetime of an asynchronous event. Node performs a lot of asynchronous
|
||||
events internally, and significant use of this API may have a
|
||||
**significant performance impact** on your application.
|
||||
|
||||
|
||||
## tracing.createAsyncListener(callbacksObj[, userData])
|
||||
|
||||
* `callbacksObj` {Object} Contains optional callbacks that will fire at
|
||||
specific times in the life cycle of the asynchronous event.
|
||||
* `userData` {Value} a value that will be passed to all callbacks.
|
||||
|
||||
Returns a constructed `AsyncListener` object.
|
||||
|
||||
To begin capturing asynchronous events pass either the `callbacksObj` or
|
||||
pass an existing `AsyncListener` instance to [`tracing.addAsyncListener()`][].
|
||||
The same `AsyncListener` instance can only be added once to the active
|
||||
queue, and subsequent attempts to add the instance will be ignored.
|
||||
|
||||
To stop capturing pass the `AsyncListener` instance to
|
||||
[`tracing.removeAsyncListener()`][]. This does _not_ mean the
|
||||
`AsyncListener` previously added will stop triggering callbacks. Once
|
||||
attached to an asynchronous event it will persist with the lifetime of the
|
||||
asynchronous call stack.
|
||||
|
||||
Explanation of function parameters:
|
||||
|
||||
|
||||
`callbacksObj`: An `Object` which may contain several optional fields:
|
||||
|
||||
* `create(userData)`: A `Function` called when an asynchronous
|
||||
event is instantiated. If a `Value` is returned then it will be attached
|
||||
to the event and overwrite any value that had been passed to
|
||||
`tracing.createAsyncListener()`'s `userData` argument. If an initial
|
||||
`userData` was passed when created, then `create()` will
|
||||
receive that as a function argument.
|
||||
|
||||
* `before(context, userData)`: A `Function` that is called immediately
|
||||
before the asynchronous callback is about to run. It will be passed both
|
||||
the `context` (i.e. `this`) of the calling function and the `userData`
|
||||
either returned from `create()` or passed during construction (if
|
||||
either occurred).
|
||||
|
||||
* `after(context, userData)`: A `Function` called immediately after
|
||||
the asynchronous event's callback has run. Note this will not be called
|
||||
if the callback throws and the error is not handled.
|
||||
|
||||
* `error(userData, error)`: A `Function` called if the event's
|
||||
callback threw. If this registered callback returns `true` then Node will
|
||||
assume the error has been properly handled and resume execution normally.
|
||||
When multiple `error()` callbacks have been registered only **one** of
|
||||
those callbacks needs to return `true` for `AsyncListener` to accept that
|
||||
the error has been handled, but all `error()` callbacks will always be run.
|
||||
|
||||
`userData`: A `Value` (i.e. anything) that will be, by default,
|
||||
attached to all new event instances. This will be overwritten if a `Value`
|
||||
is returned by `create()`.
|
||||
|
||||
Here is an example of overwriting the `userData`:
|
||||
|
||||
tracing.createAsyncListener({
|
||||
create: function listener(value) {
|
||||
// value === true
|
||||
return false;
|
||||
}, {
|
||||
before: function before(context, value) {
|
||||
// value === false
|
||||
}
|
||||
}, true);
|
||||
|
||||
**Note:** The [EventEmitter][], while used to emit status of an asynchronous
|
||||
event, is not itself asynchronous. So `create()` will not fire when
|
||||
an event is added, and `before()`/`after()` will not fire when emitted
|
||||
callbacks are called.
|
||||
|
||||
|
||||
## tracing.addAsyncListener(callbacksObj[, userData])
|
||||
## tracing.addAsyncListener(asyncListener)
|
||||
|
||||
Returns a constructed `AsyncListener` object and immediately adds it to
|
||||
the listening queue to begin capturing asynchronous events.
|
||||
|
||||
Function parameters can either be the same as
|
||||
[`tracing.createAsyncListener()`][], or a constructed `AsyncListener`
|
||||
object.
|
||||
|
||||
Example usage for capturing errors:
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var cntr = 0;
|
||||
var key = tracing.addAsyncListener({
|
||||
create: function onCreate() {
|
||||
return { uid: cntr++ };
|
||||
},
|
||||
before: function onBefore(context, storage) {
|
||||
// Write directly to stdout or we'll enter a recursive loop
|
||||
fs.writeSync(1, 'uid: ' + storage.uid + ' is about to run\n');
|
||||
},
|
||||
after: function onAfter(context, storage) {
|
||||
fs.writeSync(1, 'uid: ' + storage.uid + ' ran\n');
|
||||
},
|
||||
error: function onError(storage, err) {
|
||||
// Handle known errors
|
||||
if (err.message === 'everything is fine') {
|
||||
// Writing to stderr this time.
|
||||
fs.writeSync(2, 'handled error just threw:\n');
|
||||
fs.writeSync(2, err.stack + '\n');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
process.nextTick(function() {
|
||||
throw new Error('everything is fine');
|
||||
});
|
||||
|
||||
// Output:
|
||||
// uid: 0 is about to run
|
||||
// handled error just threw:
|
||||
// Error: really, it's ok
|
||||
// at /tmp/test2.js:27:9
|
||||
// at process._tickCallback (node.js:583:11)
|
||||
// at Function.Module.runMain (module.js:492:11)
|
||||
// at startup (node.js:123:16)
|
||||
// at node.js:1012:3
|
||||
|
||||
## tracing.removeAsyncListener(asyncListener)
|
||||
|
||||
Removes the `AsyncListener` from the listening queue.
|
||||
|
||||
Removing the `AsyncListener` from the active queue does _not_ mean the
|
||||
`asyncListener` callbacks will cease to fire on the events they've been
|
||||
registered. Subsequently, any asynchronous events fired during the
|
||||
execution of a callback will also have the same `asyncListener` callbacks
|
||||
attached for future execution. For example:
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var key = tracing.createAsyncListener({
|
||||
create: function asyncListener() {
|
||||
// Write directly to stdout or we'll enter a recursive loop
|
||||
fs.writeSync(1, 'You summoned me?\n');
|
||||
}
|
||||
});
|
||||
|
||||
// We want to begin capturing async events some time in the future.
|
||||
setTimeout(function() {
|
||||
tracing.addAsyncListener(key);
|
||||
|
||||
// Perform a few additional async events.
|
||||
setTimeout(function() {
|
||||
setImmediate(function() {
|
||||
process.nextTick(function() { });
|
||||
});
|
||||
});
|
||||
|
||||
// Removing the listener doesn't mean to stop capturing events that
|
||||
// have already been added.
|
||||
tracing.removeAsyncListener(key);
|
||||
}, 100);
|
||||
|
||||
// Output:
|
||||
// You summoned me?
|
||||
// You summoned me?
|
||||
// You summoned me?
|
||||
// You summoned me?
|
||||
|
||||
The fact that we logged 4 asynchronous events is an implementation detail
|
||||
of Node's [Timers][].
|
||||
|
||||
To stop capturing from a specific asynchronous event stack
|
||||
`tracing.removeAsyncListener()` must be called from within the call
|
||||
stack itself. For example:
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var key = tracing.createAsyncListener({
|
||||
create: function asyncListener() {
|
||||
// Write directly to stdout or we'll enter a recursive loop
|
||||
fs.writeSync(1, 'You summoned me?\n');
|
||||
}
|
||||
});
|
||||
|
||||
// We want to begin capturing async events some time in the future.
|
||||
setTimeout(function() {
|
||||
tracing.addAsyncListener(key);
|
||||
|
||||
// Perform a few additional async events.
|
||||
setImmediate(function() {
|
||||
// Stop capturing from this call stack.
|
||||
tracing.removeAsyncListener(key);
|
||||
|
||||
process.nextTick(function() { });
|
||||
});
|
||||
}, 100);
|
||||
|
||||
// Output:
|
||||
// You summoned me?
|
||||
|
||||
The user must be explicit and always pass the `AsyncListener` they wish
|
||||
to remove. It is not possible to simply remove all listeners at once.
|
||||
|
||||
|
||||
[EventEmitter]: events.html#events_class_events_eventemitter
|
||||
[Timers]: timers.html
|
||||
[`tracing.createAsyncListener()`]: #tracing_tracing_createasynclistener_asynclistener_callbacksobj_storagevalue
|
||||
[`tracing.addAsyncListener()`]: #tracing_tracing_addasynclistener_asynclistener
|
||||
[`tracing.removeAsyncListener()`]: #tracing_tracing_removeasynclistener_asynclistener
|
||||
|
||||
|
@ -32,21 +32,6 @@ var TIMEOUT_MAX = 2147483647; // 2^31-1
|
||||
|
||||
var debug = require('util').debuglog('timer');
|
||||
|
||||
var tracing = require('tracing');
|
||||
var asyncFlags = tracing._asyncFlags;
|
||||
var runAsyncQueue = tracing._runAsyncQueue;
|
||||
var loadAsyncQueue = tracing._loadAsyncQueue;
|
||||
var unloadAsyncQueue = tracing._unloadAsyncQueue;
|
||||
|
||||
// Same as in AsyncListener in env.h
|
||||
var kHasListener = 0;
|
||||
|
||||
// Do a little housekeeping.
|
||||
delete tracing._asyncFlags;
|
||||
delete tracing._runAsyncQueue;
|
||||
delete tracing._loadAsyncQueue;
|
||||
delete tracing._unloadAsyncQueue;
|
||||
|
||||
|
||||
// IDLE TIMEOUTS
|
||||
//
|
||||
@ -61,11 +46,6 @@ delete tracing._unloadAsyncQueue;
|
||||
// value = list
|
||||
var lists = {};
|
||||
|
||||
// Make Timer as monomorphic as possible.
|
||||
Timer.prototype._asyncQueue = undefined;
|
||||
Timer.prototype._asyncData = undefined;
|
||||
Timer.prototype._asyncFlags = 0;
|
||||
|
||||
// the main function - creates lists on demand and the watchers associated
|
||||
// with them.
|
||||
function insert(item, msecs) {
|
||||
@ -102,7 +82,7 @@ function listOnTimeout() {
|
||||
var now = Timer.now();
|
||||
debug('now: %s', now);
|
||||
|
||||
var diff, first, hasQueue, threw;
|
||||
var diff, first, threw;
|
||||
while (first = L.peek(list)) {
|
||||
diff = now - first._idleStart;
|
||||
if (diff < msecs) {
|
||||
@ -124,19 +104,13 @@ function listOnTimeout() {
|
||||
if (domain && domain._disposed)
|
||||
continue;
|
||||
|
||||
hasQueue = !!first._asyncQueue;
|
||||
|
||||
try {
|
||||
if (hasQueue)
|
||||
loadAsyncQueue(first);
|
||||
if (domain)
|
||||
domain.enter();
|
||||
threw = true;
|
||||
first._onTimeout();
|
||||
if (domain)
|
||||
domain.exit();
|
||||
if (hasQueue)
|
||||
unloadAsyncQueue(first);
|
||||
threw = false;
|
||||
} finally {
|
||||
if (threw) {
|
||||
@ -206,11 +180,6 @@ exports.active = function(item) {
|
||||
L.append(list, item);
|
||||
}
|
||||
}
|
||||
// Whether or not a new TimerWrap needed to be created, this should run
|
||||
// for each item. This way each "item" (i.e. timer) can properly have
|
||||
// their own domain assigned.
|
||||
if (asyncFlags[kHasListener] > 0)
|
||||
runAsyncQueue(item);
|
||||
};
|
||||
|
||||
|
||||
@ -356,18 +325,15 @@ L.init(immediateQueue);
|
||||
|
||||
function processImmediate() {
|
||||
var queue = immediateQueue;
|
||||
var domain, hasQueue, immediate;
|
||||
var domain, immediate;
|
||||
|
||||
immediateQueue = {};
|
||||
L.init(immediateQueue);
|
||||
|
||||
while (L.isEmpty(queue) === false) {
|
||||
immediate = L.shift(queue);
|
||||
hasQueue = !!immediate._asyncQueue;
|
||||
domain = immediate.domain;
|
||||
|
||||
if (hasQueue)
|
||||
loadAsyncQueue(immediate);
|
||||
if (domain)
|
||||
domain.enter();
|
||||
|
||||
@ -391,8 +357,6 @@ function processImmediate() {
|
||||
|
||||
if (domain)
|
||||
domain.exit();
|
||||
if (hasQueue)
|
||||
unloadAsyncQueue(immediate);
|
||||
}
|
||||
|
||||
// Only round-trip to C++ land if we have to. Calling clearImmediate() on an
|
||||
@ -408,11 +372,8 @@ function Immediate() { }
|
||||
|
||||
Immediate.prototype.domain = undefined;
|
||||
Immediate.prototype._onImmediate = undefined;
|
||||
Immediate.prototype._asyncQueue = undefined;
|
||||
Immediate.prototype._asyncData = undefined;
|
||||
Immediate.prototype._idleNext = undefined;
|
||||
Immediate.prototype._idlePrev = undefined;
|
||||
Immediate.prototype._asyncFlags = 0;
|
||||
|
||||
|
||||
exports.setImmediate = function(callback) {
|
||||
@ -438,9 +399,6 @@ exports.setImmediate = function(callback) {
|
||||
process._immediateCallback = processImmediate;
|
||||
}
|
||||
|
||||
// setImmediates are handled more like nextTicks.
|
||||
if (asyncFlags[kHasListener] > 0)
|
||||
runAsyncQueue(immediate);
|
||||
if (process.domain)
|
||||
immediate.domain = process.domain;
|
||||
|
||||
@ -474,7 +432,7 @@ function unrefTimeout() {
|
||||
|
||||
debug('unrefTimer fired');
|
||||
|
||||
var diff, domain, first, hasQueue, threw;
|
||||
var diff, domain, first, threw;
|
||||
while (first = L.peek(unrefList)) {
|
||||
diff = now - first._idleStart;
|
||||
|
||||
@ -492,11 +450,8 @@ function unrefTimeout() {
|
||||
|
||||
if (!first._onTimeout) continue;
|
||||
if (domain && domain._disposed) continue;
|
||||
hasQueue = !!first._asyncQueue;
|
||||
|
||||
try {
|
||||
if (hasQueue)
|
||||
loadAsyncQueue(first);
|
||||
if (domain) domain.enter();
|
||||
threw = true;
|
||||
debug('unreftimer firing timeout');
|
||||
@ -504,8 +459,6 @@ function unrefTimeout() {
|
||||
threw = false;
|
||||
if (domain)
|
||||
domain.exit();
|
||||
if (hasQueue)
|
||||
unloadAsyncQueue(first);
|
||||
} finally {
|
||||
if (threw) process.nextTick(unrefTimeout);
|
||||
}
|
||||
|
333
lib/tracing.js
333
lib/tracing.js
@ -35,13 +35,6 @@ exports._nodeInitialization = function nodeInitialization(pobj) {
|
||||
v8.getHeapStatistics = v8binding.getHeapStatistics;
|
||||
v8.setFlagsFromString = v8binding.setFlagsFromString;
|
||||
|
||||
// Part of the AsyncListener setup to share objects/callbacks with the
|
||||
// native layer.
|
||||
process._setupAsyncListener(asyncFlags,
|
||||
runAsyncQueue,
|
||||
loadAsyncQueue,
|
||||
unloadAsyncQueue);
|
||||
|
||||
// Do a little housekeeping.
|
||||
delete exports._nodeInitialization;
|
||||
};
|
||||
@ -70,329 +63,3 @@ v8.on('removeListener', function(name) {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// AsyncListener
|
||||
|
||||
// new Array() is used here because it is more efficient for sparse
|
||||
// arrays. Please *do not* change these to simple bracket notation.
|
||||
|
||||
// Track the active queue of AsyncListeners that have been added.
|
||||
var asyncQueue = new Array();
|
||||
|
||||
// Keep the stack of all contexts that have been loaded in the
|
||||
// execution chain of asynchronous events.
|
||||
var contextStack = new Array();
|
||||
var currentContext = undefined;
|
||||
|
||||
// Incremental uid for new AsyncListener instances.
|
||||
var alUid = 0;
|
||||
|
||||
// Stateful flags shared with Environment for quick JS/C++
|
||||
// communication.
|
||||
var asyncFlags = {};
|
||||
|
||||
// Prevent accidentally suppressed thrown errors from before/after.
|
||||
var inAsyncTick = false;
|
||||
|
||||
// To prevent infinite recursion when an error handler also throws
|
||||
// flag when an error is currenly being handled.
|
||||
var inErrorTick = false;
|
||||
|
||||
// Needs to be the same as src/env.h
|
||||
var kHasListener = 0;
|
||||
|
||||
// Flags to determine what async listeners are available.
|
||||
var HAS_CREATE_AL = 1 << 0;
|
||||
var HAS_BEFORE_AL = 1 << 1;
|
||||
var HAS_AFTER_AL = 1 << 2;
|
||||
var HAS_ERROR_AL = 1 << 3;
|
||||
|
||||
// _errorHandler is scoped so it's also accessible by _fatalException.
|
||||
exports._errorHandler = errorHandler;
|
||||
|
||||
// Needs to be accessible from lib/timers.js so they know when async
|
||||
// listeners are currently in queue. They'll be cleaned up once
|
||||
// references there are made.
|
||||
exports._asyncFlags = asyncFlags;
|
||||
exports._runAsyncQueue = runAsyncQueue;
|
||||
exports._loadAsyncQueue = loadAsyncQueue;
|
||||
exports._unloadAsyncQueue = unloadAsyncQueue;
|
||||
|
||||
// Public API.
|
||||
exports.createAsyncListener = createAsyncListener;
|
||||
exports.addAsyncListener = addAsyncListener;
|
||||
exports.removeAsyncListener = removeAsyncListener;
|
||||
|
||||
// Load the currently executing context as the current context, and
|
||||
// create a new asyncQueue that can receive any added queue items
|
||||
// during the executing of the callback.
|
||||
function loadContext(ctx) {
|
||||
contextStack.push(currentContext);
|
||||
currentContext = ctx;
|
||||
|
||||
asyncFlags[kHasListener] = 1;
|
||||
}
|
||||
|
||||
function unloadContext() {
|
||||
currentContext = contextStack.pop();
|
||||
|
||||
if (currentContext === undefined && asyncQueue.length === 0)
|
||||
asyncFlags[kHasListener] = 0;
|
||||
}
|
||||
|
||||
// Run all the async listeners attached when an asynchronous event is
|
||||
// instantiated.
|
||||
function runAsyncQueue(context) {
|
||||
var queue = new Array();
|
||||
var data = new Array();
|
||||
var ccQueue, i, queueItem, value;
|
||||
|
||||
context._asyncQueue = queue;
|
||||
context._asyncData = data;
|
||||
context._asyncFlags = 0;
|
||||
|
||||
inAsyncTick = true;
|
||||
|
||||
// First run through all callbacks in the currentContext. These may
|
||||
// add new AsyncListeners to the asyncQueue during execution. Hence
|
||||
// why they need to be evaluated first.
|
||||
if (currentContext) {
|
||||
ccQueue = currentContext._asyncQueue;
|
||||
context._asyncFlags |= currentContext._asyncFlags;
|
||||
for (i = 0; i < ccQueue.length; i++) {
|
||||
queueItem = ccQueue[i];
|
||||
queue[queue.length] = queueItem;
|
||||
if ((queueItem.callback_flags & HAS_CREATE_AL) === 0) {
|
||||
data[queueItem.uid] = queueItem.data;
|
||||
continue;
|
||||
}
|
||||
value = queueItem.create(queueItem.data);
|
||||
data[queueItem.uid] = (value === undefined) ? queueItem.data : value;
|
||||
}
|
||||
}
|
||||
|
||||
// Then run through all items in the asyncQueue
|
||||
if (asyncQueue) {
|
||||
for (i = 0; i < asyncQueue.length; i++) {
|
||||
queueItem = asyncQueue[i];
|
||||
// Quick way to check if an AL instance with the same uid was
|
||||
// already run from currentContext.
|
||||
if (data[queueItem.uid] !== undefined)
|
||||
continue;
|
||||
queue[queue.length] = queueItem;
|
||||
context._asyncFlags |= queueItem.callback_flags;
|
||||
if ((queueItem.callback_flags & HAS_CREATE_AL) === 0) {
|
||||
data[queueItem.uid] = queueItem.data;
|
||||
continue;
|
||||
}
|
||||
value = queueItem.create(queueItem.data);
|
||||
data[queueItem.uid] = (value === undefined) ? queueItem.data : value;
|
||||
}
|
||||
}
|
||||
|
||||
inAsyncTick = false;
|
||||
}
|
||||
|
||||
// Load the AsyncListener queue attached to context and run all
|
||||
// "before" callbacks, if they exist.
|
||||
function loadAsyncQueue(context) {
|
||||
loadContext(context);
|
||||
|
||||
if ((context._asyncFlags & HAS_BEFORE_AL) === 0)
|
||||
return;
|
||||
|
||||
var queue = context._asyncQueue;
|
||||
var data = context._asyncData;
|
||||
var i, queueItem;
|
||||
|
||||
inAsyncTick = true;
|
||||
for (i = 0; i < queue.length; i++) {
|
||||
queueItem = queue[i];
|
||||
if ((queueItem.callback_flags & HAS_BEFORE_AL) > 0)
|
||||
queueItem.before(context, data[queueItem.uid]);
|
||||
}
|
||||
inAsyncTick = false;
|
||||
}
|
||||
|
||||
// Unload the AsyncListener queue attached to context and run all
|
||||
// "after" callbacks, if they exist.
|
||||
function unloadAsyncQueue(context) {
|
||||
if ((context._asyncFlags & HAS_AFTER_AL) === 0) {
|
||||
unloadContext();
|
||||
return;
|
||||
}
|
||||
|
||||
var queue = context._asyncQueue;
|
||||
var data = context._asyncData;
|
||||
var i, queueItem;
|
||||
|
||||
inAsyncTick = true;
|
||||
for (i = 0; i < queue.length; i++) {
|
||||
queueItem = queue[i];
|
||||
if ((queueItem.callback_flags & HAS_AFTER_AL) > 0)
|
||||
queueItem.after(context, data[queueItem.uid]);
|
||||
}
|
||||
inAsyncTick = false;
|
||||
|
||||
unloadContext();
|
||||
}
|
||||
|
||||
// Handle errors that are thrown while in the context of an
|
||||
// AsyncListener. If an error is thrown from an AsyncListener
|
||||
// callback error handlers will be called once more to report
|
||||
// the error, then the application will die forcefully.
|
||||
function errorHandler(er) {
|
||||
if (inErrorTick)
|
||||
return false;
|
||||
|
||||
var handled = false;
|
||||
var i, queueItem, threw;
|
||||
|
||||
inErrorTick = true;
|
||||
|
||||
// First process error callbacks from the current context.
|
||||
if (currentContext && (currentContext._asyncFlags & HAS_ERROR_AL) > 0) {
|
||||
var queue = currentContext._asyncQueue;
|
||||
var data = currentContext._asyncData;
|
||||
for (i = 0; i < queue.length; i++) {
|
||||
queueItem = queue[i];
|
||||
if ((queueItem.callback_flags & HAS_ERROR_AL) === 0)
|
||||
continue;
|
||||
try {
|
||||
threw = true;
|
||||
// While it would be possible to pass in currentContext, if
|
||||
// the error is thrown from the "create" callback then there's
|
||||
// a chance the object hasn't been fully constructed.
|
||||
handled = queueItem.error(data[queueItem.uid], er) || handled;
|
||||
threw = false;
|
||||
} finally {
|
||||
// If the error callback thew then die quickly. Only allow the
|
||||
// exit events to be processed.
|
||||
if (threw) {
|
||||
process._exiting = true;
|
||||
process.emit('exit', 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now process callbacks from any existing queue.
|
||||
if (asyncQueue) {
|
||||
for (i = 0; i < asyncQueue.length; i++) {
|
||||
queueItem = asyncQueue[i];
|
||||
if ((queueItem.callback_flags & HAS_ERROR_AL) === 0 ||
|
||||
(data && data[queueItem.uid] !== undefined))
|
||||
continue;
|
||||
try {
|
||||
threw = true;
|
||||
handled = queueItem.error(queueItem.data, er) || handled;
|
||||
threw = false;
|
||||
} finally {
|
||||
// If the error callback thew then die quickly. Only allow the
|
||||
// exit events to be processed.
|
||||
if (threw) {
|
||||
process._exiting = true;
|
||||
process.emit('exit', 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inErrorTick = false;
|
||||
|
||||
unloadContext();
|
||||
|
||||
// TODO(trevnorris): If the error was handled, should the after callbacks
|
||||
// be fired anyways?
|
||||
|
||||
return handled && !inAsyncTick;
|
||||
}
|
||||
|
||||
// Instance function of an AsyncListener object.
|
||||
function AsyncListenerInst(callbacks, data) {
|
||||
if (typeof callbacks.create === 'function') {
|
||||
this.create = callbacks.create;
|
||||
this.callback_flags |= HAS_CREATE_AL;
|
||||
}
|
||||
if (typeof callbacks.before === 'function') {
|
||||
this.before = callbacks.before;
|
||||
this.callback_flags |= HAS_BEFORE_AL;
|
||||
}
|
||||
if (typeof callbacks.after === 'function') {
|
||||
this.after = callbacks.after;
|
||||
this.callback_flags |= HAS_AFTER_AL;
|
||||
}
|
||||
if (typeof callbacks.error === 'function') {
|
||||
this.error = callbacks.error;
|
||||
this.callback_flags |= HAS_ERROR_AL;
|
||||
}
|
||||
|
||||
this.uid = ++alUid;
|
||||
this.data = data === undefined ? null : data;
|
||||
}
|
||||
AsyncListenerInst.prototype.create = undefined;
|
||||
AsyncListenerInst.prototype.before = undefined;
|
||||
AsyncListenerInst.prototype.after = undefined;
|
||||
AsyncListenerInst.prototype.error = undefined;
|
||||
AsyncListenerInst.prototype.data = undefined;
|
||||
AsyncListenerInst.prototype.uid = 0;
|
||||
AsyncListenerInst.prototype.callback_flags = 0;
|
||||
|
||||
// Create new async listener object. Useful when instantiating a new
|
||||
// object and want the listener instance, but not add it to the stack.
|
||||
// If an existing AsyncListenerInst is passed then any new "data" is
|
||||
// ignored.
|
||||
function createAsyncListener(callbacks, data) {
|
||||
if (typeof callbacks !== 'object' || callbacks == null)
|
||||
throw new TypeError('callbacks argument must be an object');
|
||||
|
||||
if (callbacks instanceof AsyncListenerInst)
|
||||
return callbacks;
|
||||
else
|
||||
return new AsyncListenerInst(callbacks, data);
|
||||
}
|
||||
|
||||
// Add a listener to the current queue.
|
||||
function addAsyncListener(callbacks, data) {
|
||||
// Fast track if a new AsyncListenerInst has to be created.
|
||||
if (!(callbacks instanceof AsyncListenerInst)) {
|
||||
callbacks = createAsyncListener(callbacks, data);
|
||||
asyncQueue.push(callbacks);
|
||||
asyncFlags[kHasListener] = 1;
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
var inQueue = false;
|
||||
// The asyncQueue will be small. Probably always <= 3 items.
|
||||
for (var i = 0; i < asyncQueue.length; i++) {
|
||||
if (callbacks === asyncQueue[i]) {
|
||||
inQueue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the callback doesn't already exist in the queue.
|
||||
if (!inQueue) {
|
||||
asyncQueue.push(callbacks);
|
||||
asyncFlags[kHasListener] = 1;
|
||||
}
|
||||
|
||||
return callbacks;
|
||||
}
|
||||
|
||||
// Remove listener from the current queue. Though this will not remove
|
||||
// the listener from the current context. So callback propagation will
|
||||
// continue.
|
||||
function removeAsyncListener(obj) {
|
||||
for (var i = 0; i < asyncQueue.length; i++) {
|
||||
if (obj === asyncQueue[i]) {
|
||||
asyncQueue.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (asyncQueue.length > 0 || currentContext !== undefined)
|
||||
asyncFlags[kHasListener] = 1;
|
||||
else
|
||||
asyncFlags[kHasListener] = 0;
|
||||
}
|
||||
|
@ -37,20 +37,7 @@ inline AsyncWrap::AsyncWrap(Environment* env,
|
||||
v8::Handle<v8::Object> object,
|
||||
ProviderType provider)
|
||||
: BaseObject(env, object),
|
||||
async_flags_(NO_OPTIONS),
|
||||
provider_type_(provider) {
|
||||
if (!env->has_async_listener())
|
||||
return;
|
||||
|
||||
// TODO(trevnorris): Do we really need to TryCatch this call?
|
||||
v8::TryCatch try_catch;
|
||||
try_catch.SetVerbose(true);
|
||||
|
||||
v8::Local<v8::Value> val = object.As<v8::Value>();
|
||||
env->async_listener_run_function()->Call(env->process_object(), 1, &val);
|
||||
|
||||
if (!try_catch.HasCaught())
|
||||
async_flags_ |= HAS_ASYNC_LISTENER;
|
||||
}
|
||||
|
||||
|
||||
@ -59,11 +46,6 @@ inline uint32_t AsyncWrap::provider_type() const {
|
||||
}
|
||||
|
||||
|
||||
inline bool AsyncWrap::has_async_listener() {
|
||||
return async_flags_ & HAS_ASYNC_LISTENER;
|
||||
}
|
||||
|
||||
|
||||
// I hate you domains.
|
||||
inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
||||
const v8::Handle<v8::Function> cb,
|
||||
@ -79,14 +61,6 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
||||
v8::TryCatch try_catch;
|
||||
try_catch.SetVerbose(true);
|
||||
|
||||
if (has_async_listener()) {
|
||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
||||
env()->async_listener_load_function()->Call(process, 1, &val);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return v8::Undefined(env()->isolate());
|
||||
}
|
||||
|
||||
bool has_domain = domain_v->IsObject();
|
||||
if (has_domain) {
|
||||
domain = domain_v.As<v8::Object>();
|
||||
@ -119,14 +93,6 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeDomainCallback(
|
||||
}
|
||||
}
|
||||
|
||||
if (has_async_listener()) {
|
||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
||||
env()->async_listener_unload_function()->Call(process, 1, &val);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return Undefined(env()->isolate());
|
||||
}
|
||||
|
||||
Environment::TickInfo* tick_info = env()->tick_info();
|
||||
|
||||
if (tick_info->in_tick()) {
|
||||
@ -172,28 +138,12 @@ inline v8::Handle<v8::Value> AsyncWrap::MakeCallback(
|
||||
v8::TryCatch try_catch;
|
||||
try_catch.SetVerbose(true);
|
||||
|
||||
if (has_async_listener()) {
|
||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
||||
env()->async_listener_load_function()->Call(process, 1, &val);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return v8::Undefined(env()->isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> ret = cb->Call(context, argc, argv);
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
return Undefined(env()->isolate());
|
||||
}
|
||||
|
||||
if (has_async_listener()) {
|
||||
v8::Local<v8::Value> val = context.As<v8::Value>();
|
||||
env()->async_listener_unload_function()->Call(process, 1, &val);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return v8::Undefined(env()->isolate());
|
||||
}
|
||||
|
||||
Environment::TickInfo* tick_info = env()->tick_info();
|
||||
|
||||
if (tick_info->in_tick()) {
|
||||
|
@ -30,11 +30,6 @@ namespace node {
|
||||
|
||||
class AsyncWrap : public BaseObject {
|
||||
public:
|
||||
enum AsyncFlags {
|
||||
NO_OPTIONS = 0,
|
||||
HAS_ASYNC_LISTENER = 1
|
||||
};
|
||||
|
||||
enum ProviderType {
|
||||
PROVIDER_NONE = 1 << 0,
|
||||
PROVIDER_CARES = 1 << 1,
|
||||
@ -63,8 +58,6 @@ class AsyncWrap : public BaseObject {
|
||||
|
||||
inline virtual ~AsyncWrap() override = default;
|
||||
|
||||
inline bool has_async_listener();
|
||||
|
||||
inline uint32_t provider_type() const;
|
||||
|
||||
// Only call these within a valid HandleScope.
|
||||
@ -88,7 +81,6 @@ class AsyncWrap : public BaseObject {
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv);
|
||||
|
||||
uint32_t async_flags_;
|
||||
uint32_t provider_type_;
|
||||
};
|
||||
|
||||
|
@ -111,27 +111,6 @@ inline v8::Isolate* Environment::IsolateData::isolate() const {
|
||||
return isolate_;
|
||||
}
|
||||
|
||||
inline Environment::AsyncListener::AsyncListener() {
|
||||
for (int i = 0; i < kFieldsCount; ++i)
|
||||
fields_[i] = 0;
|
||||
}
|
||||
|
||||
inline uint32_t* Environment::AsyncListener::fields() {
|
||||
return fields_;
|
||||
}
|
||||
|
||||
inline int Environment::AsyncListener::fields_count() const {
|
||||
return kFieldsCount;
|
||||
}
|
||||
|
||||
inline bool Environment::AsyncListener::has_listener() const {
|
||||
return fields_[kHasListener] > 0;
|
||||
}
|
||||
|
||||
inline uint32_t Environment::AsyncListener::watched_providers() const {
|
||||
return fields_[kWatchedProviders];
|
||||
}
|
||||
|
||||
inline Environment::DomainFlag::DomainFlag() {
|
||||
for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
|
||||
}
|
||||
@ -277,16 +256,6 @@ inline v8::Isolate* Environment::isolate() const {
|
||||
return isolate_;
|
||||
}
|
||||
|
||||
inline bool Environment::has_async_listener() const {
|
||||
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
||||
return const_cast<Environment*>(this)->async_listener()->has_listener();
|
||||
}
|
||||
|
||||
inline uint32_t Environment::watched_providers() const {
|
||||
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
||||
return const_cast<Environment*>(this)->async_listener()->watched_providers();
|
||||
}
|
||||
|
||||
inline bool Environment::in_domain() const {
|
||||
// The const_cast is okay, it doesn't violate conceptual const-ness.
|
||||
return using_domains() &&
|
||||
@ -338,10 +307,6 @@ inline uv_loop_t* Environment::event_loop() const {
|
||||
return isolate_data()->event_loop();
|
||||
}
|
||||
|
||||
inline Environment::AsyncListener* Environment::async_listener() {
|
||||
return &async_listener_count_;
|
||||
}
|
||||
|
||||
inline Environment::DomainFlag* Environment::domain_flag() {
|
||||
return &domain_flag_;
|
||||
}
|
||||
|
29
src/env.h
29
src/env.h
@ -64,7 +64,6 @@ namespace node {
|
||||
V(address_string, "address") \
|
||||
V(args_string, "args") \
|
||||
V(argv_string, "argv") \
|
||||
V(async_queue_string, "_asyncQueue") \
|
||||
V(async, "async") \
|
||||
V(atime_string, "atime") \
|
||||
V(birthtime_string, "birthtime") \
|
||||
@ -250,9 +249,6 @@ namespace node {
|
||||
V(zero_return_string, "ZERO_RETURN") \
|
||||
|
||||
#define ENVIRONMENT_STRONG_PERSISTENT_PROPERTIES(V) \
|
||||
V(async_listener_run_function, v8::Function) \
|
||||
V(async_listener_load_function, v8::Function) \
|
||||
V(async_listener_unload_function, v8::Function) \
|
||||
V(binding_cache_object, v8::Object) \
|
||||
V(buffer_constructor_function, v8::Function) \
|
||||
V(context, v8::Context) \
|
||||
@ -286,28 +282,6 @@ RB_HEAD(ares_task_list, ares_task_t);
|
||||
|
||||
class Environment {
|
||||
public:
|
||||
class AsyncListener {
|
||||
public:
|
||||
inline uint32_t* fields();
|
||||
inline int fields_count() const;
|
||||
inline bool has_listener() const;
|
||||
inline uint32_t watched_providers() const;
|
||||
|
||||
private:
|
||||
friend class Environment; // So we can call the constructor.
|
||||
inline AsyncListener();
|
||||
|
||||
enum Fields {
|
||||
kHasListener,
|
||||
kWatchedProviders,
|
||||
kFieldsCount
|
||||
};
|
||||
|
||||
uint32_t fields_[kFieldsCount];
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AsyncListener);
|
||||
};
|
||||
|
||||
class DomainFlag {
|
||||
public:
|
||||
inline uint32_t* fields();
|
||||
@ -399,7 +373,6 @@ class Environment {
|
||||
|
||||
inline v8::Isolate* isolate() const;
|
||||
inline uv_loop_t* event_loop() const;
|
||||
inline bool has_async_listener() const;
|
||||
inline bool in_domain() const;
|
||||
inline uint32_t watched_providers() const;
|
||||
|
||||
@ -419,7 +392,6 @@ class Environment {
|
||||
void *arg);
|
||||
inline void FinishHandleCleanup(uv_handle_t* handle);
|
||||
|
||||
inline AsyncListener* async_listener();
|
||||
inline DomainFlag* domain_flag();
|
||||
inline TickInfo* tick_info();
|
||||
|
||||
@ -513,7 +485,6 @@ class Environment {
|
||||
uv_idle_t immediate_idle_handle_;
|
||||
uv_prepare_t idle_prepare_handle_;
|
||||
uv_check_t idle_check_handle_;
|
||||
AsyncListener async_listener_count_;
|
||||
DomainFlag domain_flag_;
|
||||
TickInfo tick_info_;
|
||||
uv_timer_t cares_timer_handle_;
|
||||
|
63
src/node.cc
63
src/node.cc
@ -918,31 +918,6 @@ Local<Value> WinapiErrnoException(Isolate* isolate,
|
||||
#endif
|
||||
|
||||
|
||||
void SetupAsyncListener(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
CHECK(args[0]->IsObject());
|
||||
CHECK(args[1]->IsFunction());
|
||||
CHECK(args[2]->IsFunction());
|
||||
CHECK(args[3]->IsFunction());
|
||||
|
||||
env->set_async_listener_run_function(args[1].As<Function>());
|
||||
env->set_async_listener_load_function(args[2].As<Function>());
|
||||
env->set_async_listener_unload_function(args[3].As<Function>());
|
||||
|
||||
Local<Object> async_listener_flag_obj = args[0].As<Object>();
|
||||
Environment::AsyncListener* async_listener = env->async_listener();
|
||||
async_listener_flag_obj->SetIndexedPropertiesToExternalArrayData(
|
||||
async_listener->fields(),
|
||||
kExternalUint32Array,
|
||||
async_listener->fields_count());
|
||||
|
||||
// Do a little housekeeping.
|
||||
env->process_object()->Delete(
|
||||
FIXED_ONE_BYTE_STRING(args.GetIsolate(), "_setupAsyncListener"));
|
||||
}
|
||||
|
||||
|
||||
void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
|
||||
@ -1026,20 +1001,6 @@ Handle<Value> MakeDomainCallback(Environment* env,
|
||||
TryCatch try_catch;
|
||||
try_catch.SetVerbose(true);
|
||||
|
||||
bool has_async_queue = false;
|
||||
|
||||
if (recv->IsObject()) {
|
||||
object = recv.As<Object>();
|
||||
// TODO(trevnorris): This is sucky for performance. Fix it.
|
||||
has_async_queue = object->Has(env->async_queue_string());
|
||||
if (has_async_queue) {
|
||||
env->async_listener_load_function()->Call(process, 1, &recv);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return Undefined(env->isolate());
|
||||
}
|
||||
}
|
||||
|
||||
bool has_domain = false;
|
||||
|
||||
if (!object.IsEmpty()) {
|
||||
@ -1077,13 +1038,6 @@ Handle<Value> MakeDomainCallback(Environment* env,
|
||||
}
|
||||
}
|
||||
|
||||
if (has_async_queue) {
|
||||
env->async_listener_unload_function()->Call(process, 1, &recv);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return Undefined(env->isolate());
|
||||
}
|
||||
|
||||
Environment::TickInfo* tick_info = env->tick_info();
|
||||
|
||||
if (tick_info->last_threw() == 1) {
|
||||
@ -1135,28 +1089,12 @@ Handle<Value> MakeCallback(Environment* env,
|
||||
TryCatch try_catch;
|
||||
try_catch.SetVerbose(true);
|
||||
|
||||
// TODO(trevnorris): This is sucky for performance. Fix it.
|
||||
bool has_async_queue =
|
||||
recv->IsObject() && recv.As<Object>()->Has(env->async_queue_string());
|
||||
if (has_async_queue) {
|
||||
env->async_listener_load_function()->Call(process, 1, &recv);
|
||||
if (try_catch.HasCaught())
|
||||
return Undefined(env->isolate());
|
||||
}
|
||||
|
||||
Local<Value> ret = callback->Call(recv, argc, argv);
|
||||
|
||||
if (try_catch.HasCaught()) {
|
||||
return Undefined(env->isolate());
|
||||
}
|
||||
|
||||
if (has_async_queue) {
|
||||
env->async_listener_unload_function()->Call(process, 1, &recv);
|
||||
|
||||
if (try_catch.HasCaught())
|
||||
return Undefined(env->isolate());
|
||||
}
|
||||
|
||||
Environment::TickInfo* tick_info = env->tick_info();
|
||||
|
||||
if (tick_info->in_tick()) {
|
||||
@ -2865,7 +2803,6 @@ void SetupProcessObject(Environment* env,
|
||||
env->SetMethod(process, "binding", Binding);
|
||||
env->SetMethod(process, "_linkedBinding", LinkedBinding);
|
||||
|
||||
env->SetMethod(process, "_setupAsyncListener", SetupAsyncListener);
|
||||
env->SetMethod(process, "_setupNextTick", SetupNextTick);
|
||||
env->SetMethod(process, "_setupDomainUse", SetupDomainUse);
|
||||
|
||||
|
41
src/node.js
41
src/node.js
@ -232,14 +232,8 @@
|
||||
};
|
||||
|
||||
startup.processFatal = function() {
|
||||
var tracing = NativeModule.require('tracing');
|
||||
var _errorHandler = tracing._errorHandler;
|
||||
// Cleanup
|
||||
delete tracing._errorHandler;
|
||||
|
||||
process._fatalException = function(er) {
|
||||
// First run through error handlers from asyncListener.
|
||||
var caught = _errorHandler(er);
|
||||
var caught;
|
||||
|
||||
if (process.domain && process.domain._errorHandler)
|
||||
caught = process.domain._errorHandler(er) || caught;
|
||||
@ -262,10 +256,6 @@
|
||||
// if we handled an error, then make sure any ticks get processed
|
||||
} else {
|
||||
var t = setImmediate(process._tickCallback);
|
||||
// Complete hack to make sure any errors thrown from async
|
||||
// listeners don't cause an infinite loop.
|
||||
if (t._asyncQueue)
|
||||
t._asyncQueue = [];
|
||||
}
|
||||
|
||||
return caught;
|
||||
@ -299,12 +289,7 @@
|
||||
};
|
||||
|
||||
startup.processNextTick = function() {
|
||||
var tracing = NativeModule.require('tracing');
|
||||
var nextTickQueue = [];
|
||||
var asyncFlags = tracing._asyncFlags;
|
||||
var _runAsyncQueue = tracing._runAsyncQueue;
|
||||
var _loadAsyncQueue = tracing._loadAsyncQueue;
|
||||
var _unloadAsyncQueue = tracing._unloadAsyncQueue;
|
||||
var microtasksScheduled = false;
|
||||
|
||||
// Used to run V8's micro task queue.
|
||||
@ -318,10 +303,6 @@
|
||||
var kIndex = 0;
|
||||
var kLength = 1;
|
||||
|
||||
// For asyncFlags.
|
||||
// *Must* match Environment::AsyncListeners::Fields in src/env.h
|
||||
var kCount = 0;
|
||||
|
||||
process.nextTick = nextTick;
|
||||
// Needs to be accessible from beyond this scope.
|
||||
process._tickCallback = _tickCallback;
|
||||
@ -368,7 +349,7 @@
|
||||
// Run callbacks that have no domain.
|
||||
// Using domains will cause this to be overridden.
|
||||
function _tickCallback() {
|
||||
var callback, hasQueue, threw, tock;
|
||||
var callback, threw, tock;
|
||||
|
||||
scheduleMicrotasks();
|
||||
|
||||
@ -376,9 +357,6 @@
|
||||
tock = nextTickQueue[tickInfo[kIndex]++];
|
||||
callback = tock.callback;
|
||||
threw = true;
|
||||
hasQueue = !!tock._asyncQueue;
|
||||
if (hasQueue)
|
||||
_loadAsyncQueue(tock);
|
||||
try {
|
||||
callback();
|
||||
threw = false;
|
||||
@ -386,8 +364,6 @@
|
||||
if (threw)
|
||||
tickDone();
|
||||
}
|
||||
if (hasQueue)
|
||||
_unloadAsyncQueue(tock);
|
||||
if (1e4 < tickInfo[kIndex])
|
||||
tickDone();
|
||||
}
|
||||
@ -396,7 +372,7 @@
|
||||
}
|
||||
|
||||
function _tickDomainCallback() {
|
||||
var callback, domain, hasQueue, threw, tock;
|
||||
var callback, domain, threw, tock;
|
||||
|
||||
scheduleMicrotasks();
|
||||
|
||||
@ -404,9 +380,6 @@
|
||||
tock = nextTickQueue[tickInfo[kIndex]++];
|
||||
callback = tock.callback;
|
||||
domain = tock.domain;
|
||||
hasQueue = !!tock._asyncQueue;
|
||||
if (hasQueue)
|
||||
_loadAsyncQueue(tock);
|
||||
if (domain)
|
||||
domain.enter();
|
||||
threw = true;
|
||||
@ -417,8 +390,6 @@
|
||||
if (threw)
|
||||
tickDone();
|
||||
}
|
||||
if (hasQueue)
|
||||
_unloadAsyncQueue(tock);
|
||||
if (1e4 < tickInfo[kIndex])
|
||||
tickDone();
|
||||
if (domain)
|
||||
@ -435,13 +406,9 @@
|
||||
|
||||
var obj = {
|
||||
callback: callback,
|
||||
domain: process.domain || null,
|
||||
_asyncQueue: undefined
|
||||
domain: process.domain || null
|
||||
};
|
||||
|
||||
if (asyncFlags[kCount] > 0)
|
||||
_runAsyncQueue(obj);
|
||||
|
||||
nextTickQueue.push(obj);
|
||||
tickInfo[kLength]++;
|
||||
}
|
||||
|
@ -1,76 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var active = null;
|
||||
var cntr = 0;
|
||||
|
||||
function onAsync0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function onAsync1() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
function onError(stor) {
|
||||
results.push(stor);
|
||||
return true;
|
||||
}
|
||||
|
||||
var results = [];
|
||||
var asyncNoHandleError0 = {
|
||||
create: onAsync0,
|
||||
error: onError
|
||||
};
|
||||
var asyncNoHandleError1 = {
|
||||
create: onAsync1,
|
||||
error: onError
|
||||
};
|
||||
|
||||
var listeners = [
|
||||
tracing.addAsyncListener(asyncNoHandleError0),
|
||||
tracing.addAsyncListener(asyncNoHandleError1)
|
||||
];
|
||||
|
||||
process.nextTick(function() {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
tracing.removeAsyncListener(listeners[0]);
|
||||
tracing.removeAsyncListener(listeners[1]);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
// Handling of errors should propagate to all listeners.
|
||||
assert.equal(results[0], 0);
|
||||
assert.equal(results[1], 1);
|
||||
assert.equal(results.length, 2);
|
||||
|
||||
console.log('ok');
|
||||
});
|
@ -1,65 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var results = [];
|
||||
var asyncNoHandleError = {
|
||||
error: function(stor) {
|
||||
results.push(1);
|
||||
}
|
||||
};
|
||||
|
||||
var asyncHandleError = {
|
||||
error: function(stor) {
|
||||
results.push(0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var listeners = [
|
||||
tracing.addAsyncListener(asyncHandleError),
|
||||
tracing.addAsyncListener(asyncNoHandleError)
|
||||
];
|
||||
|
||||
// Even if an error handler returns true, both should fire.
|
||||
process.nextTick(function() {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
tracing.removeAsyncListener(listeners[0]);
|
||||
tracing.removeAsyncListener(listeners[1]);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
// Mixed handling of errors should propagate to all listeners.
|
||||
assert.equal(results[0], 0);
|
||||
assert.equal(results[1], 1);
|
||||
assert.equal(results.length, 2);
|
||||
|
||||
console.log('ok');
|
||||
});
|
@ -1,79 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
function onAsync0() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function onAsync1() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
function onError(stor) {
|
||||
results.push(stor);
|
||||
}
|
||||
|
||||
var results = [];
|
||||
var asyncNoHandleError0 = {
|
||||
create: onAsync0,
|
||||
error: onError
|
||||
};
|
||||
var asyncNoHandleError1 = {
|
||||
create: onAsync1,
|
||||
error: onError
|
||||
};
|
||||
|
||||
var listeners = [
|
||||
tracing.addAsyncListener(asyncNoHandleError0),
|
||||
tracing.addAsyncListener(asyncNoHandleError1)
|
||||
];
|
||||
|
||||
var uncaughtFired = false;
|
||||
process.on('uncaughtException', function() {
|
||||
uncaughtFired = true;
|
||||
|
||||
// Unhandled errors should propagate to all listeners.
|
||||
assert.equal(results[0], 0);
|
||||
assert.equal(results[1], 1);
|
||||
assert.equal(results.length, 2);
|
||||
});
|
||||
|
||||
process.nextTick(function() {
|
||||
throw new Error();
|
||||
});
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
// Need to remove the async listeners or tests will always pass
|
||||
for (var i = 0; i < listeners.length; i++)
|
||||
tracing.removeAsyncListener(listeners[i]);
|
||||
|
||||
assert.ok(uncaughtFired);
|
||||
console.log('ok');
|
||||
});
|
@ -1,108 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var dns = require('dns');
|
||||
var fs = require('fs');
|
||||
var net = require('net');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var errorMsgs = [];
|
||||
var caught = 0;
|
||||
var expectCaught = 0;
|
||||
|
||||
var callbacksObj = {
|
||||
error: function(value, er) {
|
||||
var idx = errorMsgs.indexOf(er.message);
|
||||
caught++;
|
||||
|
||||
process._rawDebug('Handling error: ' + er.message);
|
||||
|
||||
if (-1 < idx)
|
||||
errorMsgs.splice(idx, 1);
|
||||
else
|
||||
throw new Error('Message not found: ' + er.message);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var listener = tracing.addAsyncListener(callbacksObj);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
tracing.removeAsyncListener(listener);
|
||||
|
||||
if (code > 0)
|
||||
return;
|
||||
|
||||
if (errorMsgs.length > 0)
|
||||
throw new Error('Errors not fired: ' + errorMsgs);
|
||||
|
||||
assert.equal(caught, expectCaught);
|
||||
process._rawDebug('ok');
|
||||
});
|
||||
|
||||
|
||||
// Net
|
||||
var iter = 3;
|
||||
for (var i = 0; i < iter; i++) {
|
||||
errorMsgs.push('net - error: server connection');
|
||||
errorMsgs.push('net - error: client data');
|
||||
errorMsgs.push('net - error: server data');
|
||||
}
|
||||
errorMsgs.push('net - error: server closed');
|
||||
|
||||
var server = net.createServer(function(c) {
|
||||
c.on('data', function() {
|
||||
if (0 === --iter) {
|
||||
server.close(function() {
|
||||
process._rawDebug('net - server closing');
|
||||
throw new Error('net - error: server closed');
|
||||
});
|
||||
expectCaught++;
|
||||
}
|
||||
process._rawDebug('net - connection received data');
|
||||
throw new Error('net - error: server data');
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
c.end('bye');
|
||||
process._rawDebug('net - connection received');
|
||||
throw new Error('net - error: server connection');
|
||||
});
|
||||
expectCaught += iter;
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
for (var i = 0; i < iter; i++)
|
||||
clientConnect();
|
||||
});
|
||||
|
||||
function clientConnect() {
|
||||
var client = net.connect(common.PORT, function() { });
|
||||
|
||||
client.on('data', function() {
|
||||
client.end('see ya');
|
||||
process._rawDebug('net - client received data');
|
||||
throw new Error('net - error: client data');
|
||||
});
|
||||
expectCaught++;
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var once = 0;
|
||||
|
||||
var results = [];
|
||||
var handlers = {
|
||||
after: function() {
|
||||
throw 1;
|
||||
},
|
||||
error: function(stor, err) {
|
||||
// Error handler must be called exactly *once*.
|
||||
once++;
|
||||
assert.equal(err, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var key = tracing.addAsyncListener(handlers);
|
||||
|
||||
var uncaughtFired = false;
|
||||
process.on('uncaughtException', function(err) {
|
||||
uncaughtFired = true;
|
||||
|
||||
assert.equal(once, 1);
|
||||
});
|
||||
|
||||
process.nextTick(function() { });
|
||||
|
||||
tracing.removeAsyncListener(key);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
assert.ok(uncaughtFired);
|
||||
console.log('ok');
|
||||
});
|
@ -1,80 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var once = 0;
|
||||
|
||||
var results = [];
|
||||
var handlers = {
|
||||
before: function() {
|
||||
throw 1;
|
||||
},
|
||||
error: function(stor, err) {
|
||||
// Must catch error thrown in before callback.
|
||||
assert.equal(err, 1);
|
||||
once++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var handlers1 = {
|
||||
before: function() {
|
||||
throw 2;
|
||||
},
|
||||
error: function(stor, err) {
|
||||
// Must catch *other* handlers throw by error callback.
|
||||
assert.equal(err, 1);
|
||||
once++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var listeners = [
|
||||
tracing.addAsyncListener(handlers),
|
||||
tracing.addAsyncListener(handlers1)
|
||||
];
|
||||
|
||||
var uncaughtFired = false;
|
||||
process.on('uncaughtException', function(err) {
|
||||
uncaughtFired = true;
|
||||
|
||||
// Both error handlers must fire.
|
||||
assert.equal(once, 2);
|
||||
});
|
||||
|
||||
process.nextTick(function() { });
|
||||
|
||||
for (var i = 0; i < listeners.length; i++)
|
||||
tracing.removeAsyncListener(listeners[i]);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
// Make sure uncaughtException actually fired.
|
||||
assert.ok(uncaughtFired);
|
||||
console.log('ok');
|
||||
});
|
||||
|
@ -1,64 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var once = 0;
|
||||
|
||||
var results = [];
|
||||
var handlers = {
|
||||
before: function() {
|
||||
throw 1;
|
||||
},
|
||||
error: function(stor, err) {
|
||||
// Error handler must be called exactly *once*.
|
||||
once++;
|
||||
assert.equal(err, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var key = tracing.addAsyncListener(handlers);
|
||||
|
||||
var uncaughtFired = false;
|
||||
process.on('uncaughtException', function(err) {
|
||||
uncaughtFired = true;
|
||||
|
||||
// Process should propagate error regardless of handlers return value.
|
||||
assert.equal(once, 1);
|
||||
});
|
||||
|
||||
process.nextTick(function() { });
|
||||
|
||||
tracing.removeAsyncListener(key);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
// Make sure that the uncaughtException actually fired.
|
||||
assert.ok(uncaughtFired);
|
||||
console.log('ok');
|
||||
});
|
@ -1,87 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var spawn = require('child_process').spawn;
|
||||
var tracing = require('tracing');
|
||||
|
||||
var checkStr = 'WRITTEN ON EXIT';
|
||||
|
||||
if (process.argv[2] === 'child')
|
||||
runChild();
|
||||
else
|
||||
runParent();
|
||||
|
||||
|
||||
function runChild() {
|
||||
var cntr = 0;
|
||||
|
||||
var key = tracing.addAsyncListener({
|
||||
error: function onError() {
|
||||
cntr++;
|
||||
throw new Error('onError');
|
||||
}
|
||||
});
|
||||
|
||||
process.on('unhandledException', function() {
|
||||
// Throwing in 'error' should bypass unhandledException.
|
||||
process.exit(2);
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
// Make sure that we can still write out to stderr even when the
|
||||
// process dies.
|
||||
process._rawDebug(checkStr);
|
||||
});
|
||||
|
||||
process.nextTick(function() {
|
||||
throw new Error('nextTick');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function runParent() {
|
||||
var childDidExit = false;
|
||||
var childStr = '';
|
||||
var child = spawn(process.execPath, [__filename, 'child']);
|
||||
child.stderr.on('data', function(chunk) {
|
||||
process._rawDebug('received data from child');
|
||||
childStr += chunk.toString();
|
||||
});
|
||||
|
||||
child.on('exit', function(code) {
|
||||
process._rawDebug('child process exiting');
|
||||
childDidExit = true;
|
||||
// This is thrown when Node throws from _fatalException.
|
||||
assert.equal(code, 7);
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
process._rawDebug('child ondata message:',
|
||||
childStr.substr(0, checkStr.length));
|
||||
|
||||
assert.ok(childDidExit);
|
||||
assert.equal(childStr.substr(0, checkStr.length), checkStr);
|
||||
console.log('ok');
|
||||
});
|
||||
}
|
||||
|
@ -1,257 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var dns = require('dns');
|
||||
var fs = require('fs');
|
||||
var net = require('net');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var addListener = tracing.addAsyncListener;
|
||||
var removeListener = tracing.removeAsyncListener;
|
||||
var errorMsgs = [];
|
||||
var currentMsg = '';
|
||||
var caught = 0;
|
||||
var expectCaught = 0;
|
||||
var exitCbRan = false;
|
||||
|
||||
var callbacksObj = {
|
||||
error: function(value, er) {
|
||||
var idx = errorMsgs.indexOf(er.message);
|
||||
|
||||
caught++;
|
||||
|
||||
if (-1 < idx)
|
||||
errorMsgs.splice(idx, 1);
|
||||
|
||||
return currentMsg === er.message;
|
||||
}
|
||||
};
|
||||
|
||||
var listener = tracing.createAsyncListener(callbacksObj);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
removeListener(listener);
|
||||
|
||||
// Something else went wrong, no need to further check.
|
||||
if (code > 0)
|
||||
return;
|
||||
|
||||
// Make sure the exit callback only runs once.
|
||||
assert.ok(!exitCbRan);
|
||||
exitCbRan = true;
|
||||
|
||||
// Check if any error messages weren't removed from the msg queue.
|
||||
if (errorMsgs.length > 0)
|
||||
throw new Error('Errors not fired: ' + errorMsgs);
|
||||
|
||||
assert.equal(caught, expectCaught, 'caught all expected errors');
|
||||
process._rawDebug('ok');
|
||||
});
|
||||
|
||||
|
||||
// Catch synchronous throws
|
||||
errorMsgs.push('sync throw');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
expectCaught++;
|
||||
currentMsg = 'sync throw';
|
||||
throw new Error(currentMsg);
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Simple cases
|
||||
errorMsgs.push('setTimeout - simple');
|
||||
errorMsgs.push('setImmediate - simple');
|
||||
errorMsgs.push('setInterval - simple');
|
||||
errorMsgs.push('process.nextTick - simple');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
setTimeout(function() {
|
||||
currentMsg = 'setTimeout - simple';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
setImmediate(function() {
|
||||
currentMsg = 'setImmediate - simple';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
var b = setInterval(function() {
|
||||
clearInterval(b);
|
||||
currentMsg = 'setInterval - simple';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
process.nextTick(function() {
|
||||
currentMsg = 'process.nextTick - simple';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Deeply nested
|
||||
errorMsgs.push('setInterval - nested');
|
||||
errorMsgs.push('setImmediate - nested');
|
||||
errorMsgs.push('process.nextTick - nested');
|
||||
errorMsgs.push('setTimeout2 - nested');
|
||||
errorMsgs.push('setTimeout - nested');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
setTimeout(function() {
|
||||
process.nextTick(function() {
|
||||
setImmediate(function() {
|
||||
var b = setInterval(function() {
|
||||
clearInterval(b);
|
||||
currentMsg = 'setInterval - nested';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
currentMsg = 'setImmediate - nested';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
currentMsg = 'process.nextTick - nested';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
setTimeout(function() {
|
||||
currentMsg = 'setTimeout2 - nested';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
currentMsg = 'setTimeout - nested';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// FS
|
||||
errorMsgs.push('fs - file does not exist');
|
||||
errorMsgs.push('fs - exists');
|
||||
errorMsgs.push('fs - realpath');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
fs.stat('does not exist', function(err, stats) {
|
||||
currentMsg = 'fs - file does not exist';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
fs.exists('hi all', function(exists) {
|
||||
currentMsg = 'fs - exists';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
fs.realpath('/some/path', function(err, resolved) {
|
||||
currentMsg = 'fs - realpath';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Nested FS
|
||||
errorMsgs.push('fs - nested file does not exist');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
setTimeout(function() {
|
||||
setImmediate(function() {
|
||||
var b = setInterval(function() {
|
||||
clearInterval(b);
|
||||
process.nextTick(function() {
|
||||
fs.stat('does not exist', function(err, stats) {
|
||||
currentMsg = 'fs - nested file does not exist';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Net
|
||||
errorMsgs.push('net - connection listener');
|
||||
errorMsgs.push('net - client connect');
|
||||
errorMsgs.push('net - server listening');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
var server = net.createServer(function(c) {
|
||||
server.close();
|
||||
currentMsg = 'net - connection listener';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
var client = net.connect(common.PORT, function() {
|
||||
client.end();
|
||||
currentMsg = 'net - client connect';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
currentMsg = 'net - server listening';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// DNS
|
||||
errorMsgs.push('dns - lookup');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
dns.lookup('localhost', function() {
|
||||
currentMsg = 'dns - lookup';
|
||||
throw new Error(currentMsg);
|
||||
});
|
||||
expectCaught++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
@ -1,70 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var addListener = tracing.addAsyncListener;
|
||||
var removeListener = tracing.removeAsyncListener;
|
||||
var caught = [];
|
||||
var expect = [];
|
||||
|
||||
var callbacksObj = {
|
||||
error: function(value, er) {
|
||||
process._rawDebug('caught', er.message);
|
||||
caught.push(er.message);
|
||||
return (expect.indexOf(er.message) !== -1);
|
||||
}
|
||||
};
|
||||
|
||||
var listener = tracing.createAsyncListener(callbacksObj);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
removeListener(listener);
|
||||
|
||||
if (code > 0)
|
||||
return;
|
||||
|
||||
expect = expect.sort();
|
||||
caught = caught.sort();
|
||||
|
||||
process._rawDebug('expect', expect);
|
||||
process._rawDebug('caught', caught);
|
||||
assert.deepEqual(caught, expect, 'caught all expected errors');
|
||||
process._rawDebug('ok');
|
||||
});
|
||||
|
||||
|
||||
expect.push('immediate simple a');
|
||||
expect.push('immediate simple b');
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
// Tests for a setImmediate specific bug encountered while implementing
|
||||
// AsyncListeners.
|
||||
setImmediate(function() {
|
||||
throw new Error('immediate simple a');
|
||||
});
|
||||
setImmediate(function() {
|
||||
throw new Error('immediate simple b');
|
||||
});
|
||||
removeListener(listener);
|
||||
});
|
@ -1,47 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
var val;
|
||||
var callbacks = {
|
||||
create: function() {
|
||||
return 42;
|
||||
},
|
||||
before: function() {
|
||||
tracing.removeAsyncListener(listener);
|
||||
tracing.addAsyncListener(listener);
|
||||
},
|
||||
after: function(context, storage) {
|
||||
val = storage;
|
||||
}
|
||||
};
|
||||
|
||||
var listener = tracing.addAsyncListener(callbacks);
|
||||
|
||||
process.nextTick(function() {});
|
||||
|
||||
process.on('exit', function(status) {
|
||||
tracing.removeAsyncListener(listener);
|
||||
assert.equal(status, 0);
|
||||
assert.equal(val, 42);
|
||||
});
|
@ -1,53 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
var set = 0;
|
||||
|
||||
var asyncNoHandleError = {
|
||||
before: function() {
|
||||
set++;
|
||||
},
|
||||
after: function() {
|
||||
set++;
|
||||
}
|
||||
}
|
||||
|
||||
var key = tracing.addAsyncListener(asyncNoHandleError);
|
||||
|
||||
tracing.removeAsyncListener(key);
|
||||
|
||||
process.nextTick(function() { });
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
// The async handler should never be called.
|
||||
assert.equal(set, 0);
|
||||
console.log('ok');
|
||||
});
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
var done = false;
|
||||
var callbacks = {
|
||||
before: function() {
|
||||
tracing.removeAsyncListener(listener);
|
||||
},
|
||||
after: function() {
|
||||
done = true;
|
||||
}
|
||||
};
|
||||
|
||||
var listener = tracing.addAsyncListener(callbacks);
|
||||
|
||||
process.nextTick(function() {});
|
||||
|
||||
process.on('exit', function(status) {
|
||||
tracing.removeAsyncListener(listener);
|
||||
assert.equal(status, 0);
|
||||
assert.ok(done);
|
||||
});
|
@ -1,58 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var set = 0;
|
||||
var asyncNoHandleError = {
|
||||
error: function() {
|
||||
set++;
|
||||
}
|
||||
}
|
||||
|
||||
var key = tracing.addAsyncListener(asyncNoHandleError);
|
||||
|
||||
process.nextTick(function() {
|
||||
throw 1;
|
||||
});
|
||||
|
||||
tracing.removeAsyncListener(key);
|
||||
|
||||
var uncaughtFired = false;
|
||||
process.on('uncaughtException', function() {
|
||||
uncaughtFired = true;
|
||||
|
||||
// Throwing should call the error handler once, then propagate to
|
||||
// uncaughtException
|
||||
assert.equal(set, 1);
|
||||
});
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
assert.ok(uncaughtFired);
|
||||
console.log('ok');
|
||||
});
|
@ -1,53 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var set = 0;
|
||||
var asyncNoHandleError = {
|
||||
before: function() {
|
||||
set++;
|
||||
},
|
||||
after: function() {
|
||||
set++;
|
||||
}
|
||||
}
|
||||
|
||||
var key = tracing.addAsyncListener(asyncNoHandleError);
|
||||
|
||||
process.nextTick(function() { });
|
||||
|
||||
tracing.removeAsyncListener(key);
|
||||
|
||||
process.on('exit', function(code) {
|
||||
// If the exit code isn't ok then return early to throw the stack that
|
||||
// caused the bad return code.
|
||||
if (code !== 0)
|
||||
return;
|
||||
|
||||
// Calling removeAsyncListener *after* a callback is scheduled
|
||||
// should not affect the handler from responding to the callback.
|
||||
assert.equal(set, 2);
|
||||
console.log('ok');
|
||||
});
|
||||
|
@ -1,59 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var net = require('net');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var errMsg = 'net - error: server connection';
|
||||
var cntr = 0;
|
||||
var al = tracing.addAsyncListener({
|
||||
error: function(stor, er) {
|
||||
cntr++;
|
||||
process._rawDebug('Handling error: ' + er.message);
|
||||
assert.equal(errMsg, er.message);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
process.on('exit', function(status) {
|
||||
tracing.removeAsyncListener(al);
|
||||
|
||||
console.log('exit status:', status);
|
||||
assert.equal(status, 0);
|
||||
console.log('cntr:', cntr);
|
||||
assert.equal(cntr, 1);
|
||||
console.log('ok');
|
||||
});
|
||||
|
||||
|
||||
var server = net.createServer(function(c) {
|
||||
this.close();
|
||||
throw new Error(errMsg);
|
||||
});
|
||||
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
net.connect(common.PORT, function() {
|
||||
this.destroy();
|
||||
});
|
||||
});
|
@ -1,46 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var cntr = 0;
|
||||
var al = tracing.createAsyncListener({
|
||||
create: function() { cntr++; },
|
||||
});
|
||||
|
||||
process.on('exit', function() {
|
||||
assert.equal(cntr, 4);
|
||||
console.log('ok');
|
||||
});
|
||||
|
||||
tracing.addAsyncListener(al);
|
||||
|
||||
process.nextTick(function() {
|
||||
tracing.addAsyncListener(al);
|
||||
process.nextTick(function() {
|
||||
tracing.addAsyncListener(al);
|
||||
process.nextTick(function() {
|
||||
process.nextTick(function() { });
|
||||
});
|
||||
});
|
||||
});
|
@ -1,48 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var tracing = require('tracing');
|
||||
|
||||
// If there is an uncaughtException listener then the error thrown from
|
||||
// "before" will be considered handled, thus calling setImmediate to
|
||||
// finish execution of the nextTickQueue. This in turn will cause "before"
|
||||
// to fire again, entering into an infinite loop.
|
||||
// So the asyncQueue is cleared from the returned setImmediate in
|
||||
// _fatalException to prevent this from happening.
|
||||
var cntr = 0;
|
||||
|
||||
|
||||
tracing.addAsyncListener({
|
||||
before: function() {
|
||||
if (++cntr > 1) {
|
||||
// Can't throw since uncaughtException will also catch that.
|
||||
process._rawDebug('Error: Multiple before callbacks called');
|
||||
process.exit(1);
|
||||
}
|
||||
throw new Error('before');
|
||||
}
|
||||
});
|
||||
|
||||
process.on('uncaughtException', function() { });
|
||||
|
||||
process.nextTick();
|
@ -1,188 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
var common = require('../common');
|
||||
var assert = require('assert');
|
||||
var net = require('net');
|
||||
var fs = require('fs');
|
||||
var dgram = require('dgram');
|
||||
var tracing = require('tracing');
|
||||
|
||||
var addListener = tracing.addAsyncListener;
|
||||
var removeListener = tracing.removeAsyncListener;
|
||||
var actualAsync = 0;
|
||||
var expectAsync = 0;
|
||||
|
||||
var callbacks = {
|
||||
create: function onAsync() {
|
||||
actualAsync++;
|
||||
}
|
||||
};
|
||||
|
||||
var listener = tracing.createAsyncListener(callbacks);
|
||||
|
||||
process.on('exit', function() {
|
||||
process._rawDebug('expected', expectAsync);
|
||||
process._rawDebug('actual ', actualAsync);
|
||||
// TODO(trevnorris): Not a great test. If one was missed, but others
|
||||
// overflowed then the test would still pass.
|
||||
assert.ok(actualAsync >= expectAsync);
|
||||
});
|
||||
|
||||
|
||||
// Test listeners side-by-side
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
var b = setInterval(function() {
|
||||
clearInterval(b);
|
||||
});
|
||||
expectAsync++;
|
||||
|
||||
var c = setInterval(function() {
|
||||
clearInterval(c);
|
||||
});
|
||||
expectAsync++;
|
||||
|
||||
setTimeout(function() { });
|
||||
expectAsync++;
|
||||
|
||||
setTimeout(function() { });
|
||||
expectAsync++;
|
||||
|
||||
process.nextTick(function() { });
|
||||
expectAsync++;
|
||||
|
||||
process.nextTick(function() { });
|
||||
expectAsync++;
|
||||
|
||||
setImmediate(function() { });
|
||||
expectAsync++;
|
||||
|
||||
setImmediate(function() { });
|
||||
expectAsync++;
|
||||
|
||||
setTimeout(function() { }, 10);
|
||||
expectAsync++;
|
||||
|
||||
setTimeout(function() { }, 10);
|
||||
expectAsync++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Async listeners should propagate with nested callbacks
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
var interval = 3;
|
||||
|
||||
process.nextTick(function() {
|
||||
setTimeout(function() {
|
||||
setImmediate(function() {
|
||||
var i = setInterval(function() {
|
||||
if (--interval <= 0)
|
||||
clearInterval(i);
|
||||
});
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
process.nextTick(function() {
|
||||
setImmediate(function() {
|
||||
setTimeout(function() { }, 20);
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Test triggers with two async listeners
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
addListener(listener);
|
||||
|
||||
setTimeout(function() {
|
||||
process.nextTick(function() { });
|
||||
expectAsync += 2;
|
||||
});
|
||||
expectAsync += 2;
|
||||
|
||||
removeListener(listener);
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Test callbacks from fs I/O
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
fs.stat('something random', function(err, stat) { });
|
||||
expectAsync++;
|
||||
|
||||
setImmediate(function() {
|
||||
fs.stat('random again', function(err, stat) { });
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Test net I/O
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
var server = net.createServer(function(c) { });
|
||||
expectAsync++;
|
||||
|
||||
server.listen(common.PORT, function() {
|
||||
server.close();
|
||||
expectAsync++;
|
||||
});
|
||||
expectAsync++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
||||
|
||||
|
||||
// Test UDP
|
||||
process.nextTick(function() {
|
||||
addListener(listener);
|
||||
|
||||
var server = dgram.createSocket('udp4');
|
||||
expectAsync++;
|
||||
|
||||
server.bind(common.PORT);
|
||||
|
||||
server.close();
|
||||
expectAsync++;
|
||||
|
||||
removeListener(listener);
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user