Skip to content

Commit 2b252ac

Browse files
felixgery
authored andcommitted
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
1 parent bd6c08a commit 2b252ac

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

src/node.cc

+44-2
Original file line numberDiff line numberDiff line change
@@ -524,9 +524,51 @@ static void OnFatalError(const char* location, const char* message) {
524524
exit(1);
525525
}
526526

527+
static int uncaught_exception_counter = 0;
528+
527529
void FatalException(TryCatch &try_catch) {
528-
ReportException(&try_catch);
529-
exit(1);
530+
HandleScope scope;
531+
532+
// Check if uncaught_exception_counter indicates a recursion
533+
if (uncaught_exception_counter > 0) {
534+
ReportException(&try_catch);
535+
exit(1);
536+
}
537+
538+
Local<Value> listeners_v = process->Get(String::NewSymbol("listeners"));
539+
assert(listeners_v->IsFunction());
540+
541+
Local<Function> listeners = Local<Function>::Cast(listeners_v);
542+
543+
Local<String> uncaught_exception = String::NewSymbol("uncaughtException");
544+
545+
Local<Value> argv[1] = { uncaught_exception };
546+
Local<Value> ret = listeners->Call(process, 1, argv);
547+
548+
assert(ret->IsArray());
549+
550+
Local<Array> listener_array = Local<Array>::Cast(ret);
551+
552+
uint32_t length = listener_array->Length();
553+
// Report and exit if process has no "uncaughtException" listener
554+
if (length == 0) {
555+
ReportException(&try_catch);
556+
exit(1);
557+
}
558+
559+
// Otherwise fire the process "uncaughtException" event
560+
Local<Value> emit_v = process->Get(String::NewSymbol("emit"));
561+
assert(emit_v->IsFunction());
562+
563+
Local<Function> emit = Local<Function>::Cast(emit_v);
564+
565+
Local<Value> error = try_catch.Exception();
566+
Local<Value> event_argv[2] = { uncaught_exception, error };
567+
568+
uncaught_exception_counter++;
569+
emit->Call(process, 2, event_argv);
570+
// Decrement so we know if the next exception is a recursion or not
571+
uncaught_exception_counter--;
530572
}
531573

532574
static ev_async eio_watcher;

src/node.js

-1
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,5 @@ if (process.ARGV[1].charAt(0) != "/" && !/^http:\/\//.exec(process.ARGV[1])) {
677677
process.mainModule = createModule(".");
678678
var loadPromise = new process.Promise();
679679
process.mainModule.load(process.ARGV[1], loadPromise);
680-
loadPromise.wait();
681680

682681
}()); // end annonymous namespace
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
process.mixin(require("./common"));
2+
3+
var MESSAGE = 'catch me if you can';
4+
var caughtException = false;
5+
6+
process.addListener('uncaughtException', function (e) {
7+
puts("uncaught exception! 1");
8+
assertEquals(MESSAGE, e.message);
9+
caughtException = true;
10+
});
11+
12+
process.addListener('uncaughtException', function (e) {
13+
puts("uncaught exception! 2");
14+
assertEquals(MESSAGE, e.message);
15+
caughtException = true;
16+
});
17+
18+
setTimeout(function() {
19+
throw new Error(MESSAGE);
20+
}, 10);
21+
22+
process.addListener("exit", function () {
23+
puts("exit");
24+
assertTrue(caughtException);
25+
});

0 commit comments

Comments
 (0)