Browse Source

Implement process "uncaughtException" event

This event can be used to overwrite the default exception mechanism which
reports the exception and kills the node process.

See google group post:
http://groups.google.com/group/nodejs/browse_thread/thread/9721dc3a2638446f
v0.7.4-release
Felix Geisendörfer 15 years ago
committed by Ryan Dahl
parent
commit
2b252acea4
  1. 42
      src/node.cc
  2. 1
      src/node.js
  3. 25
      test/mjsunit/test-exception-handler.js

42
src/node.cc

@ -524,11 +524,53 @@ static void OnFatalError(const char* location, const char* message) {
exit(1);
}
static int uncaught_exception_counter = 0;
void FatalException(TryCatch &try_catch) {
HandleScope scope;
// Check if uncaught_exception_counter indicates a recursion
if (uncaught_exception_counter > 0) {
ReportException(&try_catch);
exit(1);
}
Local<Value> listeners_v = process->Get(String::NewSymbol("listeners"));
assert(listeners_v->IsFunction());
Local<Function> listeners = Local<Function>::Cast(listeners_v);
Local<String> uncaught_exception = String::NewSymbol("uncaughtException");
Local<Value> argv[1] = { uncaught_exception };
Local<Value> ret = listeners->Call(process, 1, argv);
assert(ret->IsArray());
Local<Array> listener_array = Local<Array>::Cast(ret);
uint32_t length = listener_array->Length();
// Report and exit if process has no "uncaughtException" listener
if (length == 0) {
ReportException(&try_catch);
exit(1);
}
// Otherwise fire the process "uncaughtException" event
Local<Value> emit_v = process->Get(String::NewSymbol("emit"));
assert(emit_v->IsFunction());
Local<Function> emit = Local<Function>::Cast(emit_v);
Local<Value> error = try_catch.Exception();
Local<Value> event_argv[2] = { uncaught_exception, error };
uncaught_exception_counter++;
emit->Call(process, 2, event_argv);
// Decrement so we know if the next exception is a recursion or not
uncaught_exception_counter--;
}
static ev_async eio_watcher;
// Called from the main thread.

1
src/node.js

@ -677,6 +677,5 @@ if (process.ARGV[1].charAt(0) != "/" && !/^http:\/\//.exec(process.ARGV[1])) {
process.mainModule = createModule(".");
var loadPromise = new process.Promise();
process.mainModule.load(process.ARGV[1], loadPromise);
loadPromise.wait();
}()); // end annonymous namespace

25
test/mjsunit/test-exception-handler.js

@ -0,0 +1,25 @@
process.mixin(require("./common"));
var MESSAGE = 'catch me if you can';
var caughtException = false;
process.addListener('uncaughtException', function (e) {
puts("uncaught exception! 1");
assertEquals(MESSAGE, e.message);
caughtException = true;
});
process.addListener('uncaughtException', function (e) {
puts("uncaught exception! 2");
assertEquals(MESSAGE, e.message);
caughtException = true;
});
setTimeout(function() {
throw new Error(MESSAGE);
}, 10);
process.addListener("exit", function () {
puts("exit");
assertTrue(caughtException);
});
Loading…
Cancel
Save