|
|
|
'use strict';
|
|
|
|
require('../common');
|
domain: Properly exit() on domain disposal
This addresses #4034. There are two problems happening:
1. The domain is not exited automatically when calling dispose() on it.
Then, since the domain is disposed, attempting to exit it again will do
nothing.
2. The active domain is stored on process.domain. Since thrown errors
call `process.emit('uncaughtException', er)`, and the process is an
event emitter with a `.domain` member, it re-enters the domain a second
time before calling the error handler, pushing it onto the stack again.
Thus, if the handler calls `domain.dispose()`, then the domain is now on
the stack twice, and cannot be exited properly. Since the domain is
disposed, any subsequent IO will be no-op'ed, since we've declared that
this context is done and best forgotten.
The solution here is twofold:
1. In EventEmitter.emit, do not enter the domain if `this===process`.
2. Automatically exit the domain when calling `domain.dispose()`.
12 years ago
|
|
|
var assert = require('assert');
|
|
|
|
var domain = require('domain');
|
|
|
|
var disposalFailed = false;
|
|
|
|
|
|
|
|
// no matter what happens, we should increment a 10 times.
|
|
|
|
var a = 0;
|
|
|
|
log();
|
|
|
|
function log() {
|
domain: Properly exit() on domain disposal
This addresses #4034. There are two problems happening:
1. The domain is not exited automatically when calling dispose() on it.
Then, since the domain is disposed, attempting to exit it again will do
nothing.
2. The active domain is stored on process.domain. Since thrown errors
call `process.emit('uncaughtException', er)`, and the process is an
event emitter with a `.domain` member, it re-enters the domain a second
time before calling the error handler, pushing it onto the stack again.
Thus, if the handler calls `domain.dispose()`, then the domain is now on
the stack twice, and cannot be exited properly. Since the domain is
disposed, any subsequent IO will be no-op'ed, since we've declared that
this context is done and best forgotten.
The solution here is twofold:
1. In EventEmitter.emit, do not enter the domain if `this===process`.
2. Automatically exit the domain when calling `domain.dispose()`.
12 years ago
|
|
|
console.log(a++, process.domain);
|
|
|
|
if (a < 10) setTimeout(log, 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
// in 50ms we'll throw an error.
|
|
|
|
setTimeout(err, 50);
|
|
|
|
function err() {
|
domain: Properly exit() on domain disposal
This addresses #4034. There are two problems happening:
1. The domain is not exited automatically when calling dispose() on it.
Then, since the domain is disposed, attempting to exit it again will do
nothing.
2. The active domain is stored on process.domain. Since thrown errors
call `process.emit('uncaughtException', er)`, and the process is an
event emitter with a `.domain` member, it re-enters the domain a second
time before calling the error handler, pushing it onto the stack again.
Thus, if the handler calls `domain.dispose()`, then the domain is now on
the stack twice, and cannot be exited properly. Since the domain is
disposed, any subsequent IO will be no-op'ed, since we've declared that
this context is done and best forgotten.
The solution here is twofold:
1. In EventEmitter.emit, do not enter the domain if `this===process`.
2. Automatically exit the domain when calling `domain.dispose()`.
12 years ago
|
|
|
var d = domain.create();
|
|
|
|
d.on('error', handle);
|
|
|
|
d.run(err2);
|
|
|
|
|
|
|
|
function err2() {
|
|
|
|
// this timeout should never be called, since the domain gets
|
|
|
|
// disposed when the error happens.
|
|
|
|
setTimeout(function() {
|
|
|
|
console.error('This should not happen.');
|
|
|
|
disposalFailed = true;
|
|
|
|
process.exit(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
// this function doesn't exist, and throws an error as a result.
|
|
|
|
err3(); // eslint-disable-line no-undef
|
domain: Properly exit() on domain disposal
This addresses #4034. There are two problems happening:
1. The domain is not exited automatically when calling dispose() on it.
Then, since the domain is disposed, attempting to exit it again will do
nothing.
2. The active domain is stored on process.domain. Since thrown errors
call `process.emit('uncaughtException', er)`, and the process is an
event emitter with a `.domain` member, it re-enters the domain a second
time before calling the error handler, pushing it onto the stack again.
Thus, if the handler calls `domain.dispose()`, then the domain is now on
the stack twice, and cannot be exited properly. Since the domain is
disposed, any subsequent IO will be no-op'ed, since we've declared that
this context is done and best forgotten.
The solution here is twofold:
1. In EventEmitter.emit, do not enter the domain if `this===process`.
2. Automatically exit the domain when calling `domain.dispose()`.
12 years ago
|
|
|
}
|
|
|
|
|
|
|
|
function handle(e) {
|
|
|
|
// this should clean up everything properly.
|
|
|
|
d.dispose();
|
|
|
|
console.error(e);
|
|
|
|
console.error('in handler', process.domain, process.domain === d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
process.on('exit', function() {
|
|
|
|
assert.equal(a, 10);
|
|
|
|
assert.equal(disposalFailed, false);
|
|
|
|
console.log('ok');
|
|
|
|
});
|