Skip to content

Commit

Permalink
Implement process "uncaughtException" event
Browse files Browse the repository at this point in the history
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
  • Loading branch information
felixge authored and ry committed Nov 14, 2009
1 parent bd6c08a commit 2b252ac
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 3 deletions.
46 changes: 44 additions & 2 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -524,9 +524,51 @@ static void OnFatalError(const char* location, const char* message) {
exit(1);
}

static int uncaught_exception_counter = 0;

void FatalException(TryCatch &try_catch) {
ReportException(&try_catch);
exit(1);
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;
Expand Down
1 change: 0 additions & 1 deletion src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 25 additions & 0 deletions test/mjsunit/test-exception-handler.js
Original file line number Diff line number Diff line change
@@ -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);
});

0 comments on commit 2b252ac

Please # to comment.