@@ -51,8 +51,10 @@ import { EventBuilder } from './EventBuilder';
5151import { ExceptionlessClient } from './ExceptionlessClient' ;
5252import { Utils } from './Utils' ;
5353
54- const EXIT :string = 'exit' ;
55- const UNCAUGHT_EXCEPTION :string = 'uncaughtException' ;
54+ const EXIT : string = 'exit' ;
55+ const UNCAUGHT_EXCEPTION : string = 'uncaughtException' ;
56+ const SIGINT : string = 'SIGINT' ;
57+ const SIGINT_CODE : number = 2 ;
5658
5759var defaults = Configuration . defaults ;
5860defaults . environmentInfoCollector = new NodeEnvironmentInfoCollector ( ) ;
@@ -61,34 +63,51 @@ defaults.exitController = new NodeExitController();
6163defaults . requestInfoCollector = new NodeRequestInfoCollector ( ) ;
6264defaults . submissionClient = new NodeSubmissionClient ( ) ;
6365
64- function getListenerCount ( emitter , event ) : number {
66+ function getListenerCount ( emitter , event : string ) : number {
6567 if ( emitter . listenerCount ) {
6668 return emitter . listenerCount ( event ) ;
6769 }
68-
6970 return require ( "events" ) . listenerCount ( emitter , event ) ;
7071}
7172
72- process . on ( UNCAUGHT_EXCEPTION , function ( error :Error ) {
73- ExceptionlessClient . default . submitUnhandledException ( error , UNCAUGHT_EXCEPTION ) ;
73+ /*
74+ * Adding a event handler for 'uncaughtException' modifies the default
75+ * Node behavior, so it won't exit or log to the console. Instead,
76+ * we hijack the event emitter and forward the exception to the callback.
77+ */
78+ function onUncaughtException ( callback : ( error : Error ) => void ) {
79+ var originalEmit = process . emit ;
80+
81+ process . emit = function ( type : string , error : Error ) {
82+ if ( type === UNCAUGHT_EXCEPTION ) {
83+ callback ( error ) ;
84+ }
7485
75- /*
76- * Default Node behavior: If this is the only uncaught-listener, we still exit.
77- * Discussion: https://nodejs.org/api/process.html#process_event_uncaughtexception
78- */
79- var uncaughtListenerCount = getListenerCount ( process , UNCAUGHT_EXCEPTION ) ;
80- if ( uncaughtListenerCount <= 1 ) {
81- process . exit ( 1 ) ;
86+ return originalEmit . apply ( this , arguments ) ;
8287 }
88+ }
89+
90+ onUncaughtException ( function ( error : Error ) {
91+ ExceptionlessClient . default . submitUnhandledException ( error , UNCAUGHT_EXCEPTION ) ;
8392} ) ;
8493
85- process . on ( EXIT , function ( code :number ) {
94+ /*
95+ * We cannot hijack SIGINT, so if there are no other handlers,
96+ * we just reproduce default Node.js behavior by exiting.
97+ */
98+ process . on ( SIGINT , function ( ) {
99+ if ( getListenerCount ( process , SIGINT ) <= 1 ) {
100+ process . exit ( 128 + SIGINT_CODE ) ;
101+ }
102+ } )
103+
104+ process . on ( EXIT , function ( code : number ) {
86105 /**
87106 * exit codes: https://nodejs.org/api/process.html#process_event_exit
88107 * From now on, only synchronous code may run. As soon as this method
89108 * ends, the application inevitably will exit.
90109 */
91- function getExitCodeReason ( code :number ) : string {
110+ function getExitCodeReason ( code : number ) : string {
92111 if ( code === 1 ) {
93112 return 'Uncaught Fatal Exception' ;
94113 }
@@ -129,10 +148,6 @@ process.on(EXIT, function (code:number) {
129148 return 'Invalid Debug Argument' ;
130149 }
131150
132- if ( code > 128 ) {
133- return 'Signal Exits' ;
134- }
135-
136151 return null ;
137152 }
138153
0 commit comments