Skip to content

Instantly share code, notes, and snippets.

@trevnorris
Last active August 29, 2015 14:09
Show Gist options
  • Save trevnorris/be1dee9d3fb4bc467b1c to your computer and use it in GitHub Desktop.
Save trevnorris/be1dee9d3fb4bc467b1c to your computer and use it in GitHub Desktop.
diff --git a/lib/domain.js b/lib/domain.js
index afaa922..39e90f4 100644
--- a/lib/domain.js
+++ b/lib/domain.js
@@ -33,7 +33,11 @@ var endMethods = ['end', 'abort', 'destroy', 'destroySoon'];
events.usingDomains = true;
// let the process know we're using domains
-process._usingDomains();
+// The return value let's us know whether --abort-on-uncaught-exception was
+// passed to Node.
+if (process._usingDomains()) {
+ process._aoue = true;
+}
exports.Domain = Domain;
@@ -180,7 +184,12 @@ Domain.prototype.bind = function(cb, interceptError) {
}
self.enter();
- var ret = cb.apply(this, arguments);
+ try {
+ var ret = cb.apply(this, arguments);
+ } catch(e) {
+ if (!process._fatalException(e))
+ throw e;
+ }
self.exit();
return ret;
};
diff --git a/src/node.cc b/src/node.cc
index 18c743f..8582df2 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -127,6 +127,7 @@ static Persistent<String> exit_symbol;
static Persistent<String> disposed_symbol;
+static bool abort_on_uncaught_exception = false;
static bool print_eval = false;
static bool force_repl = false;
static bool trace_deprecation = false;
@@ -926,7 +927,7 @@ Handle<Value> UsingDomains(const Arguments& args) {
process->Set(String::New("_currentTickHandler"), ndt);
process_tickCallback.Dispose(); // Possibly already set by MakeCallback().
process_tickCallback = Persistent<Function>::New(tdc);
- return Undefined();
+ return abort_on_uncaught_exception ? True() : False();
}
@@ -1922,6 +1923,11 @@ static void OnFatalError(const char* location, const char* message) {
void FatalException(TryCatch &try_catch) {
HandleScope scope;
+ if (abort_on_uncaught_exception && !process->Get(domain_symbol)->IsObject()) {
+ ReportException(try_catch, true);
+ abort();
+ }
+
if (fatal_exception_symbol.IsEmpty())
fatal_exception_symbol = NODE_PSYMBOL("_fatalException");
@@ -1944,6 +1950,11 @@ void FatalException(TryCatch &try_catch) {
// this will return true if the JS layer handled it, false otherwise
Local<Value> caught = fatal_f->Call(process, ARRAY_SIZE(argv), argv);
+ if (abort_on_uncaught_exception && !caught->BooleanValue()) {
+ ReportException(try_catch, true);
+ abort();
+ }
+
if (fatal_try_catch.HasCaught()) {
// the fatal exception function threw, so we must exit
ReportException(fatal_try_catch, true);
@@ -2571,6 +2582,8 @@ static void ParseArgs(int argc, char **argv) {
if (strstr(arg, "--debug") == arg) {
ParseDebugOpt(arg);
argv[i] = const_cast<char*>("");
+ } else if (strstr(arg, "--abort-on-uncaught-exception") == arg) {
+ abort_on_uncaught_exception = true;
} else if (strcmp(arg, "--version") == 0 || strcmp(arg, "-v") == 0) {
printf("%s\n", NODE_VERSION);
exit(0);
diff --git a/src/node.js b/src/node.js
index b54ff51..df8e5b3 100644
--- a/src/node.js
+++ b/src/node.js
@@ -265,8 +265,11 @@
var parentDomain = domainStack[domainStack.length - 1];
process.domain = domainModule.active = parentDomain;
caught = process._fatalException(er2);
- } else
+ } else {
caught = false;
+ if (process._aoue)
+ return caught;
+ }
}
} else {
caught = process.emit('uncaughtException', er);
process.on('uncaughtException', function() {
console.log('caught an uncaught exception');
});
var d = require('domain').create();
d.on('error', function() {
console.log('domain error caught');
});
d.run(function() {
throw new Error('from inside domain');
});
require('fs').readFile('not here', 'utf8', d.intercept(function(data) {
console.log('readFile complete');
throw new Error('throw from readFile cb');
}));
setTimeout(function() {
throw new Error('threw from timer');
}, 1000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment