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
This commit is contained in:
parent
bd6c08a984
commit
2b252acea4
42
src/node.cc
42
src/node.cc
@ -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) {
|
||||
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;
|
||||
|
@ -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
Normal file
25
test/mjsunit/test-exception-handler.js
Normal file
@ -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…
x
Reference in New Issue
Block a user