Skip to content
This repository has been archived by the owner on Oct 16, 2021. It is now read-only.

Commit

Permalink
domains: port caeb677 from v0.10 to v0.12
Browse files Browse the repository at this point in the history
caeb677
Do not abort the process if an error is thrown from within a domain,
an error handler is setup for the domain and
--abort-on-uncaught-exception was passed on the command line.

However, if an error is thrown from within the top-level domain's
error handler and --abort-on-uncaught-exception was passed on the
command line, make the process abort.

Fixes: nodejs#8877

Fixes: nodejs#8877
PR-URL: nodejs#25835
Reviewed-By: misterdjules - Julien Gilli <jgilli@nodejs.org>

Conflicts:
	lib/domain.js
	src/env.h
	test/simple/test-domain-with-abort-on-uncaught-exception.js
  • Loading branch information
whitlockjc authored and jBarz committed Feb 1, 2017
1 parent 5580a10 commit 14e30c5
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 15 deletions.
19 changes: 18 additions & 1 deletion src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,21 @@ static bool TopDomainHasErrorHandler(const Environment* env) {
}


static bool IsDomainActive(const Environment* env) {
if (!env->using_domains()) {
return false;
}

Local<Array> domain_array = env->domain_array().As<Array>();
uint32_t domains_array_length = domain_array->Length();
if (domains_array_length == 0)
return false;

Local<Value> domain_v = domain_array->Get(0);
return !domain_v->IsNull();
}


bool ShouldAbortOnUncaughtException(v8::Isolate* isolate) {
Environment* env = Environment::GetCurrent(isolate);
Local<Object> process_object = env->process_object();
Expand All @@ -1080,7 +1095,7 @@ bool ShouldAbortOnUncaughtException(v8::Isolate* isolate) {
bool isEmittingTopLevelDomainError =
process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();

return isEmittingTopLevelDomainError || !TopDomainHasErrorHandler(env);
return !IsDomainActive(env) || isEmittingTopLevelDomainError;
}


Expand Down Expand Up @@ -3764,6 +3779,8 @@ void Init(int* argc,
node_isolate = Isolate::New();
Isolate::Scope isolate_scope(node_isolate);

node_isolate->SetAbortOnUncaughtException(ShouldAbortOnUncaughtException);

#ifdef __POSIX__
// Raise the open file descriptor limit.
{ // NOLINT (whitespace/braces)
Expand Down
58 changes: 44 additions & 14 deletions test/simple/test-domain-with-abort-on-uncaught-exception.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@

var assert = require('assert');

var common = require('../common');

/*
* The goal of this test is to make sure that:
*
Expand Down Expand Up @@ -141,27 +139,59 @@ if (process.argv[2] === 'child') {
});

child.on('exit', function onChildExited(exitCode, signal) {
var expectedExitCode = 0;
// We use an array of values since the actual signal can differ across
// compilers.
var expectedSignal = [null];

// When throwing errors from the top-level domain error handler
// outside of a try/catch block, the process should not exit gracefully
if (!options.useTryCatch && options.throwInDomainErrHandler) {
// If the top-level domain's error handler does not throw,
// the process must exit gracefully, whether or not
// --abort_on_uncaught_exception was passed on the command line
expectedExitCode = 7;
if (cmdLineOption === '--abort_on_uncaught_exception') {
assert(common.nodeProcessAborted(exitCode, signal),
'process should have aborted, but did not');
} else {
// By default, uncaught exceptions make node exit with an exit
// code of 7.
assert.equal(exitCode, 7);
assert.equal(signal, null);
// If the top-level domain's error handler throws, and only if
// --abort_on_uncaught_exception is passed on the command line,
// the process must abort.
//
// We use an array of values since the actual exit code can differ
// across compilers.
expectedExitCode = [132, 134];

// On Linux, v8 raises SIGTRAP when aborting because
// the "debug break" flag is on by default
if (process.platform === 'linux')
expectedExitCode.push(133);

// On some platforms with KSH being the default shell
// (like SmartOS), when a process aborts, KSH exits with an exit
// code that is greater than 256, and thus the exit code emitted
// with the 'exit' event is null and the signal is set to either
// SIGABRT or SIGILL.
if (process.platform === 'sunos') {
expectedExitCode = null;
expectedSignal = ['SIGABRT', 'SIGILL'];
}

// On Windows, v8's base::OS::Abort also triggers a debug breakpoint
// which makes the process exit with code -2147483645
if (process.platform === 'win32')
expectedExitCode = [-2147483645, 3221225477];
}
}

if (Array.isArray(expectedSignal)) {
assert.ok(expectedSignal.indexOf(signal) > -1);
} else {
// If the top-level domain's error handler does not throw,
// the process must exit gracefully, whether or not
// --abort_on_uncaught_exception was passed on the command line
assert.equal(exitCode, 0);
assert.equal(signal, null);
assert.equal(signal, expectedSignal);
}

if (Array.isArray(expectedExitCode)) {
assert.ok(expectedExitCode.indexOf(exitCode) > -1);
} else {
assert.equal(exitCode, expectedExitCode);
}
});
}
Expand Down

0 comments on commit 14e30c5

Please sign in to comment.