@@ -59,6 +59,20 @@ Domain.prototype._disposed = undefined;
59
59
// Called by process._fatalException in case an error was thrown.
60
60
Domain . prototype . _errorHandler = function errorHandler ( er ) {
61
61
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
+
62
76
// ignore errors on disposed domains.
63
77
//
64
78
// XXX This is a bit stupid. We should probably get rid of
@@ -71,38 +85,54 @@ Domain.prototype._errorHandler = function errorHandler(er) {
71
85
er . domain = this ;
72
86
er . domainThrown = true ;
73
87
}
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 ) ;
85
88
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 ;
98
107
}
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 ;
104
135
}
105
- return caught ;
106
136
}
107
137
return caught ;
108
138
} ;
0 commit comments