@@ -59,6 +59,20 @@ Domain.prototype._disposed = undefined;
5959// Called by process._fatalException in case an error was thrown.
6060Domain . prototype . _errorHandler = function errorHandler ( er ) {
6161 var caught = false ;
62+ var self = this ;
63+
64+ function emitError ( ) {
65+ var handled = self . emit ( 'error' , er ) ;
66+
67+ // Exit all domains on the stack. Uncaught exceptions end the
68+ // current tick and no domains should be left on the stack
69+ // between ticks.
70+ stack . length = 0 ;
71+ exports . active = process . domain = null ;
72+
73+ return handled ;
74+ }
75+
6276 // ignore errors on disposed domains.
6377 //
6478 // XXX This is a bit stupid. We should probably get rid of
@@ -71,38 +85,54 @@ Domain.prototype._errorHandler = function errorHandler(er) {
7185 er . domain = this ;
7286 er . domainThrown = true ;
7387 }
74- // wrap this in a try/catch so we don't get infinite throwing
75- try {
76- // One of three things will happen here.
77- //
78- // 1. There is a handler, caught = true
79- // 2. There is no handler, caught = false
80- // 3. It throws, caught = false
81- //
82- // If caught is false after this, then there's no need to exit()
83- // the domain, because we're going to crash the process anyway.
84- caught = this . emit ( 'error' , er ) ;
8588
86- // Exit all domains on the stack. Uncaught exceptions end the
87- // current tick and no domains should be left on the stack
88- // between ticks.
89- stack . length = 0 ;
90- exports . active = process . domain = null ;
91- } catch ( er2 ) {
92- // The domain error handler threw! oh no!
93- // See if another domain can catch THIS error,
94- // or else crash on the original one.
95- // If the user already exited it, then don't double-exit.
96- if ( this === exports . active ) {
97- stack . pop ( ) ;
89+ // The top-level domain-handler is handled separately.
90+ //
91+ // The reason is that if V8 was passed a command line option
92+ // asking it to abort on an uncaught exception (currently
93+ // "--abort-on-uncaught-exception"), we want an uncaught exception
94+ // in the top-level domain error handler to make the
95+ // process abort. Using try/catch here would always make V8 think
96+ // that these exceptions are caught, and thus would prevent it from
97+ // aborting in these cases.
98+ if ( stack . length === 1 ) {
99+ try {
100+ // Set the _emittingTopLevelDomainError so that we know that, even
101+ // if technically the top-level domain is still active, it would
102+ // be ok to abort on an uncaught exception at this point
103+ process . _emittingTopLevelDomainError = true ;
104+ caught = emitError ( ) ;
105+ } finally {
106+ process . _emittingTopLevelDomainError = false ;
98107 }
99- if ( stack . length ) {
100- exports . active = process . domain = stack [ stack . length - 1 ] ;
101- caught = process . _fatalException ( er2 ) ;
102- } else {
103- caught = false ;
108+ } else {
109+ // wrap this in a try/catch so we don't get infinite throwing
110+ try {
111+ // One of three things will happen here.
112+ //
113+ // 1. There is a handler, caught = true
114+ // 2. There is no handler, caught = false
115+ // 3. It throws, caught = false
116+ //
117+ // If caught is false after this, then there's no need to exit()
118+ // the domain, because we're going to crash the process anyway.
119+ caught = emitError ( ) ;
120+ } catch ( er2 ) {
121+ // The domain error handler threw! oh no!
122+ // See if another domain can catch THIS error,
123+ // or else crash on the original one.
124+ // If the user already exited it, then don't double-exit.
125+ if ( this === exports . active ) {
126+ stack . pop ( ) ;
127+ }
128+ if ( stack . length ) {
129+ exports . active = process . domain = stack [ stack . length - 1 ] ;
130+ caught = process . _fatalException ( er2 ) ;
131+ } else {
132+ caught = false ;
133+ }
134+ return caught ;
104135 }
105- return caught ;
106136 }
107137 return caught ;
108138} ;
0 commit comments