@@ -77,6 +77,20 @@ Domain.prototype._disposed = undefined;
7777// Called by process._fatalException in case an error was thrown.
7878Domain . prototype . _errorHandler = function errorHandler ( er ) {
7979 var caught = false ;
80+ var self = this ;
81+
82+ function emitError ( ) {
83+ var handled = self . emit ( 'error' , er ) ;
84+
85+ // Exit all domains on the stack. Uncaught exceptions end the
86+ // current tick and no domains should be left on the stack
87+ // between ticks.
88+ stack . length = 0 ;
89+ exports . active = process . domain = null ;
90+
91+ return handled ;
92+ }
93+
8094 // ignore errors on disposed domains.
8195 //
8296 // XXX This is a bit stupid. We should probably get rid of
@@ -89,38 +103,54 @@ Domain.prototype._errorHandler = function errorHandler(er) {
89103 er . domain = this ;
90104 er . domainThrown = true ;
91105 }
92- // wrap this in a try/catch so we don't get infinite throwing
93- try {
94- // One of three things will happen here.
95- //
96- // 1. There is a handler, caught = true
97- // 2. There is no handler, caught = false
98- // 3. It throws, caught = false
99- //
100- // If caught is false after this, then there's no need to exit()
101- // the domain, because we're going to crash the process anyway.
102- caught = this . emit ( 'error' , er ) ;
103106
104- // Exit all domains on the stack. Uncaught exceptions end the
105- // current tick and no domains should be left on the stack
106- // between ticks.
107- stack . length = 0 ;
108- exports . active = process . domain = null ;
109- } catch ( er2 ) {
110- // The domain error handler threw! oh no!
111- // See if another domain can catch THIS error,
112- // or else crash on the original one.
113- // If the user already exited it, then don't double-exit.
114- if ( this === exports . active ) {
115- stack . pop ( ) ;
107+ // The top-level domain-handler is handled separately.
108+ //
109+ // The reason is that if V8 was passed a command line option
110+ // asking it to abort on an uncaught exception (currently
111+ // "--abort-on-uncaught-exception"), we want an uncaught exception
112+ // in the top-level domain error handler to make the
113+ // process abort. Using try/catch here would always make V8 think
114+ // that these exceptions are caught, and thus would prevent it from
115+ // aborting in these cases.
116+ if ( stack . length === 1 ) {
117+ try {
118+ // Set the _emittingTopLevelDomainError so that we know that, even
119+ // if technically the top-level domain is still active, it would
120+ // be ok to abort on an uncaught exception at this point
121+ process . _emittingTopLevelDomainError = true ;
122+ caught = emitError ( ) ;
123+ } finally {
124+ process . _emittingTopLevelDomainError = false ;
116125 }
117- if ( stack . length ) {
118- exports . active = process . domain = stack [ stack . length - 1 ] ;
119- caught = process . _fatalException ( er2 ) ;
120- } else {
121- caught = false ;
126+ } else {
127+ // wrap this in a try/catch so we don't get infinite throwing
128+ try {
129+ // One of three things will happen here.
130+ //
131+ // 1. There is a handler, caught = true
132+ // 2. There is no handler, caught = false
133+ // 3. It throws, caught = false
134+ //
135+ // If caught is false after this, then there's no need to exit()
136+ // the domain, because we're going to crash the process anyway.
137+ caught = emitError ( ) ;
138+ } catch ( er2 ) {
139+ // The domain error handler threw! oh no!
140+ // See if another domain can catch THIS error,
141+ // or else crash on the original one.
142+ // If the user already exited it, then don't double-exit.
143+ if ( this === exports . active ) {
144+ stack . pop ( ) ;
145+ }
146+ if ( stack . length ) {
147+ exports . active = process . domain = stack [ stack . length - 1 ] ;
148+ caught = process . _fatalException ( er2 ) ;
149+ } else {
150+ caught = false ;
151+ }
152+ return caught ;
122153 }
123- return caught ;
124154 }
125155 return caught ;
126156} ;
0 commit comments