Skip to content

Commit 6a7a59a

Browse files
addaleaxMylesBorins
authored andcommitted
src: remove ClearFatalExceptionHandlers()
At its call sites, `ClearFatalExceptionHandlers()` was used to make the process crash as soon as possible once an exception occurred, without giving JS land a chance to interfere. `ClearFatalExceptionHandlers()` awkwardly removed the current domain and any `uncaughtException` handlers, whereas a clearer way is to execute the relevant reporting (and `exit()`) code directly. PR-URL: #17333 Refs: #17159 Refs: #17324 Reviewed-By: Anatoli Papirovski <[email protected]> Reviewed-By: Timothy Gu <[email protected]> Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: Andreas Madsen <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]>
1 parent 6e3a8be commit 6a7a59a

File tree

4 files changed

+51
-78
lines changed

4 files changed

+51
-78
lines changed

src/async_wrap.cc

+15-38
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static void DestroyAsyncIdsCallback(uv_timer_t* handle) {
144144
Context::Scope context_scope(env->context());
145145
Local<Function> fn = env->async_hooks_destroy_function();
146146

147-
TryCatch try_catch(env->isolate());
147+
FatalTryCatch try_catch(env);
148148

149149
do {
150150
std::vector<double> destroy_async_id_list;
@@ -157,11 +157,8 @@ static void DestroyAsyncIdsCallback(uv_timer_t* handle) {
157157
MaybeLocal<Value> ret = fn->Call(
158158
env->context(), Undefined(env->isolate()), 1, &async_id_value);
159159

160-
if (ret.IsEmpty()) {
161-
ClearFatalExceptionHandlers(env);
162-
FatalException(env->isolate(), try_catch);
163-
UNREACHABLE();
164-
}
160+
if (ret.IsEmpty())
161+
return;
165162
}
166163
} while (!env->destroy_async_id_list()->empty());
167164
}
@@ -175,14 +172,9 @@ void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) {
175172

176173
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
177174
Local<Function> fn = env->async_hooks_promise_resolve_function();
178-
TryCatch try_catch(env->isolate());
179-
MaybeLocal<Value> ar = fn->Call(
180-
env->context(), Undefined(env->isolate()), 1, &async_id_value);
181-
if (ar.IsEmpty()) {
182-
ClearFatalExceptionHandlers(env);
183-
FatalException(env->isolate(), try_catch);
184-
UNREACHABLE();
185-
}
175+
FatalTryCatch try_catch(env);
176+
fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)
177+
.FromMaybe(Local<Value>());
186178
}
187179

188180

@@ -209,14 +201,9 @@ void AsyncWrap::EmitBefore(Environment* env, double async_id) {
209201

210202
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
211203
Local<Function> fn = env->async_hooks_before_function();
212-
TryCatch try_catch(env->isolate());
213-
MaybeLocal<Value> ar = fn->Call(
214-
env->context(), Undefined(env->isolate()), 1, &async_id_value);
215-
if (ar.IsEmpty()) {
216-
ClearFatalExceptionHandlers(env);
217-
FatalException(env->isolate(), try_catch);
218-
UNREACHABLE();
219-
}
204+
FatalTryCatch try_catch(env);
205+
fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)
206+
.FromMaybe(Local<Value>());
220207
}
221208

222209

@@ -245,14 +232,9 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
245232
// end of _fatalException().
246233
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
247234
Local<Function> fn = env->async_hooks_after_function();
248-
TryCatch try_catch(env->isolate());
249-
MaybeLocal<Value> ar = fn->Call(
250-
env->context(), Undefined(env->isolate()), 1, &async_id_value);
251-
if (ar.IsEmpty()) {
252-
ClearFatalExceptionHandlers(env);
253-
FatalException(env->isolate(), try_catch);
254-
UNREACHABLE();
255-
}
235+
FatalTryCatch try_catch(env);
236+
fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)
237+
.FromMaybe(Local<Value>());
256238
}
257239

258240
class PromiseWrap : public AsyncWrap {
@@ -753,14 +735,9 @@ void AsyncWrap::EmitAsyncInit(Environment* env,
753735
object,
754736
};
755737

756-
TryCatch try_catch(env->isolate());
757-
MaybeLocal<Value> ret = init_fn->Call(
758-
env->context(), object, arraysize(argv), argv);
759-
760-
if (ret.IsEmpty()) {
761-
ClearFatalExceptionHandlers(env);
762-
FatalException(env->isolate(), try_catch);
763-
}
738+
FatalTryCatch try_catch(env);
739+
init_fn->Call(env->context(), object, arraysize(argv), argv)
740+
.FromMaybe(Local<Value>());
764741
}
765742

766743

src/node.cc

+15-22
Original file line numberDiff line numberDiff line change
@@ -1818,6 +1818,8 @@ void AppendExceptionLine(Environment* env,
18181818
static void ReportException(Environment* env,
18191819
Local<Value> er,
18201820
Local<Message> message) {
1821+
CHECK(!er.IsEmpty());
1822+
CHECK(!message.IsEmpty());
18211823
HandleScope scope(env->isolate());
18221824

18231825
AppendExceptionLine(env, er, message, FATAL_ERROR);
@@ -1887,6 +1889,10 @@ static void ReportException(Environment* env,
18871889
}
18881890

18891891
fflush(stderr);
1892+
1893+
#if HAVE_INSPECTOR
1894+
env->inspector_agent()->FatalException(er, message);
1895+
#endif
18901896
}
18911897

18921898

@@ -2746,6 +2752,15 @@ NO_RETURN void FatalError(const char* location, const char* message) {
27462752
}
27472753

27482754

2755+
FatalTryCatch::~FatalTryCatch() {
2756+
if (HasCaught()) {
2757+
HandleScope scope(env_->isolate());
2758+
ReportException(env_, *this);
2759+
exit(7);
2760+
}
2761+
}
2762+
2763+
27492764
void FatalException(Isolate* isolate,
27502765
Local<Value> error,
27512766
Local<Message> message) {
@@ -2788,9 +2803,6 @@ void FatalException(Isolate* isolate,
27882803
}
27892804

27902805
if (exit_code) {
2791-
#if HAVE_INSPECTOR
2792-
env->inspector_agent()->FatalException(error, message);
2793-
#endif
27942806
exit(exit_code);
27952807
}
27962808
}
@@ -2810,25 +2822,6 @@ static void OnMessage(Local<Message> message, Local<Value> error) {
28102822
FatalException(Isolate::GetCurrent(), error, message);
28112823
}
28122824

2813-
2814-
void ClearFatalExceptionHandlers(Environment* env) {
2815-
Local<Object> process = env->process_object();
2816-
Local<Value> events =
2817-
process->Get(env->context(), env->events_string()).ToLocalChecked();
2818-
2819-
if (events->IsObject()) {
2820-
events.As<Object>()->Set(
2821-
env->context(),
2822-
OneByteString(env->isolate(), "uncaughtException"),
2823-
Undefined(env->isolate())).FromJust();
2824-
}
2825-
2826-
process->Set(
2827-
env->context(),
2828-
env->domain_string(),
2829-
Undefined(env->isolate())).FromJust();
2830-
}
2831-
28322825
// Call process.emitWarning(str), fmt is a snprintf() format string
28332826
void ProcessEmitWarning(Environment* env, const char* fmt, ...) {
28342827
char warning[1024];

src/node_internals.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,17 @@ void AppendExceptionLine(Environment* env,
270270

271271
NO_RETURN void FatalError(const char* location, const char* message);
272272

273+
// Like a `TryCatch` but exits the process if an exception was caught.
274+
class FatalTryCatch : public v8::TryCatch {
275+
public:
276+
explicit FatalTryCatch(Environment* env)
277+
: TryCatch(env->isolate()), env_(env) {}
278+
~FatalTryCatch();
279+
280+
private:
281+
Environment* env_;
282+
};
283+
273284
void ProcessEmitWarning(Environment* env, const char* fmt, ...);
274285

275286
void FillStatsArray(double* fields, const uv_stat_t* s);
@@ -323,11 +334,6 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
323334
uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
324335
};
325336

326-
// Clear any domain and/or uncaughtException handlers to force the error's
327-
// propagation and shutdown the process. Use this to force the process to exit
328-
// by clearing all callbacks that could handle the error.
329-
void ClearFatalExceptionHandlers(Environment* env);
330-
331337
namespace Buffer {
332338
v8::MaybeLocal<v8::Object> Copy(Environment* env, const char* data, size_t len);
333339
v8::MaybeLocal<v8::Object> New(Environment* env, size_t size);

src/node_url.cc

+10-13
Original file line numberDiff line numberDiff line change
@@ -2172,19 +2172,16 @@ const Local<Value> URL::ToObject(Environment* env) const {
21722172
};
21732173
SetArgs(env, argv, &context_);
21742174

2175-
TryCatch try_catch(isolate);
2176-
2177-
// The SetURLConstructor method must have been called already to
2178-
// set the constructor function used below. SetURLConstructor is
2179-
// called automatically when the internal/url.js module is loaded
2180-
// during the internal/bootstrap_node.js processing.
2181-
MaybeLocal<Value> ret =
2182-
env->url_constructor_function()
2183-
->Call(env->context(), undef, 9, argv);
2184-
2185-
if (ret.IsEmpty()) {
2186-
ClearFatalExceptionHandlers(env);
2187-
FatalException(isolate, try_catch);
2175+
MaybeLocal<Value> ret;
2176+
{
2177+
FatalTryCatch try_catch(env);
2178+
2179+
// The SetURLConstructor method must have been called already to
2180+
// set the constructor function used below. SetURLConstructor is
2181+
// called automatically when the internal/url.js module is loaded
2182+
// during the internal/bootstrap_node.js processing.
2183+
ret = env->url_constructor_function()
2184+
->Call(env->context(), undef, arraysize(argv), argv);
21882185
}
21892186

21902187
return ret.ToLocalChecked();

0 commit comments

Comments
 (0)