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

Commit 14e30c5

Browse files
whitlockjcjBarz
authored andcommitted
domains: port caeb677 from v0.10 to v0.12
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 <[email protected]> Conflicts: lib/domain.js src/env.h test/simple/test-domain-with-abort-on-uncaught-exception.js
1 parent 5580a10 commit 14e30c5

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

src/node.cc

+18-1
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,21 @@ static bool TopDomainHasErrorHandler(const Environment* env) {
10721072
}
10731073

10741074

1075+
static bool IsDomainActive(const Environment* env) {
1076+
if (!env->using_domains()) {
1077+
return false;
1078+
}
1079+
1080+
Local<Array> domain_array = env->domain_array().As<Array>();
1081+
uint32_t domains_array_length = domain_array->Length();
1082+
if (domains_array_length == 0)
1083+
return false;
1084+
1085+
Local<Value> domain_v = domain_array->Get(0);
1086+
return !domain_v->IsNull();
1087+
}
1088+
1089+
10751090
bool ShouldAbortOnUncaughtException(v8::Isolate* isolate) {
10761091
Environment* env = Environment::GetCurrent(isolate);
10771092
Local<Object> process_object = env->process_object();
@@ -1080,7 +1095,7 @@ bool ShouldAbortOnUncaughtException(v8::Isolate* isolate) {
10801095
bool isEmittingTopLevelDomainError =
10811096
process_object->Get(emitting_top_level_domain_error_key)->BooleanValue();
10821097

1083-
return isEmittingTopLevelDomainError || !TopDomainHasErrorHandler(env);
1098+
return !IsDomainActive(env) || isEmittingTopLevelDomainError;
10841099
}
10851100

10861101

@@ -3764,6 +3779,8 @@ void Init(int* argc,
37643779
node_isolate = Isolate::New();
37653780
Isolate::Scope isolate_scope(node_isolate);
37663781

3782+
node_isolate->SetAbortOnUncaughtException(ShouldAbortOnUncaughtException);
3783+
37673784
#ifdef __POSIX__
37683785
// Raise the open file descriptor limit.
37693786
{ // NOLINT (whitespace/braces)

test/simple/test-domain-with-abort-on-uncaught-exception.js

+44-14
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121

2222
var assert = require('assert');
2323

24-
var common = require('../common');
25-
2624
/*
2725
* The goal of this test is to make sure that:
2826
*
@@ -141,27 +139,59 @@ if (process.argv[2] === 'child') {
141139
});
142140

143141
child.on('exit', function onChildExited(exitCode, signal) {
142+
var expectedExitCode = 0;
143+
// We use an array of values since the actual signal can differ across
144+
// compilers.
145+
var expectedSignal = [null];
146+
144147
// When throwing errors from the top-level domain error handler
145148
// outside of a try/catch block, the process should not exit gracefully
146149
if (!options.useTryCatch && options.throwInDomainErrHandler) {
147150
// If the top-level domain's error handler does not throw,
148151
// the process must exit gracefully, whether or not
149152
// --abort_on_uncaught_exception was passed on the command line
153+
expectedExitCode = 7;
150154
if (cmdLineOption === '--abort_on_uncaught_exception') {
151-
assert(common.nodeProcessAborted(exitCode, signal),
152-
'process should have aborted, but did not');
153-
} else {
154-
// By default, uncaught exceptions make node exit with an exit
155-
// code of 7.
156-
assert.equal(exitCode, 7);
157-
assert.equal(signal, null);
155+
// If the top-level domain's error handler throws, and only if
156+
// --abort_on_uncaught_exception is passed on the command line,
157+
// the process must abort.
158+
//
159+
// We use an array of values since the actual exit code can differ
160+
// across compilers.
161+
expectedExitCode = [132, 134];
162+
163+
// On Linux, v8 raises SIGTRAP when aborting because
164+
// the "debug break" flag is on by default
165+
if (process.platform === 'linux')
166+
expectedExitCode.push(133);
167+
168+
// On some platforms with KSH being the default shell
169+
// (like SmartOS), when a process aborts, KSH exits with an exit
170+
// code that is greater than 256, and thus the exit code emitted
171+
// with the 'exit' event is null and the signal is set to either
172+
// SIGABRT or SIGILL.
173+
if (process.platform === 'sunos') {
174+
expectedExitCode = null;
175+
expectedSignal = ['SIGABRT', 'SIGILL'];
176+
}
177+
178+
// On Windows, v8's base::OS::Abort also triggers a debug breakpoint
179+
// which makes the process exit with code -2147483645
180+
if (process.platform === 'win32')
181+
expectedExitCode = [-2147483645, 3221225477];
158182
}
183+
}
184+
185+
if (Array.isArray(expectedSignal)) {
186+
assert.ok(expectedSignal.indexOf(signal) > -1);
159187
} else {
160-
// If the top-level domain's error handler does not throw,
161-
// the process must exit gracefully, whether or not
162-
// --abort_on_uncaught_exception was passed on the command line
163-
assert.equal(exitCode, 0);
164-
assert.equal(signal, null);
188+
assert.equal(signal, expectedSignal);
189+
}
190+
191+
if (Array.isArray(expectedExitCode)) {
192+
assert.ok(expectedExitCode.indexOf(exitCode) > -1);
193+
} else {
194+
assert.equal(exitCode, expectedExitCode);
165195
}
166196
});
167197
}

0 commit comments

Comments
 (0)