Skip to content

Commit a012672

Browse files
committed
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 3c62f33 commit a012672

File tree

4 files changed

+51
-78
lines changed

4 files changed

+51
-78
lines changed

src/async_wrap.cc

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ RetainedObjectInfo* WrapperInfo(uint16_t class_id, Local<Value> wrapper) {
140140
static void DestroyAsyncIdsCallback(Environment* env, void* data) {
141141
Local<Function> fn = env->async_hooks_destroy_function();
142142

143-
TryCatch try_catch(env->isolate());
143+
FatalTryCatch try_catch(env);
144144

145145
do {
146146
std::vector<double> destroy_async_id_list;
@@ -153,11 +153,8 @@ static void DestroyAsyncIdsCallback(Environment* env, void* data) {
153153
MaybeLocal<Value> ret = fn->Call(
154154
env->context(), Undefined(env->isolate()), 1, &async_id_value);
155155

156-
if (ret.IsEmpty()) {
157-
ClearFatalExceptionHandlers(env);
158-
FatalException(env->isolate(), try_catch);
159-
UNREACHABLE();
160-
}
156+
if (ret.IsEmpty())
157+
return;
161158
}
162159
} while (!env->destroy_async_id_list()->empty());
163160
}
@@ -171,14 +168,9 @@ void AsyncWrap::EmitPromiseResolve(Environment* env, double async_id) {
171168

172169
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
173170
Local<Function> fn = env->async_hooks_promise_resolve_function();
174-
TryCatch try_catch(env->isolate());
175-
MaybeLocal<Value> ar = fn->Call(
176-
env->context(), Undefined(env->isolate()), 1, &async_id_value);
177-
if (ar.IsEmpty()) {
178-
ClearFatalExceptionHandlers(env);
179-
FatalException(env->isolate(), try_catch);
180-
UNREACHABLE();
181-
}
171+
FatalTryCatch try_catch(env);
172+
fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)
173+
.FromMaybe(Local<Value>());
182174
}
183175

184176

@@ -205,14 +197,9 @@ void AsyncWrap::EmitBefore(Environment* env, double async_id) {
205197

206198
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
207199
Local<Function> fn = env->async_hooks_before_function();
208-
TryCatch try_catch(env->isolate());
209-
MaybeLocal<Value> ar = fn->Call(
210-
env->context(), Undefined(env->isolate()), 1, &async_id_value);
211-
if (ar.IsEmpty()) {
212-
ClearFatalExceptionHandlers(env);
213-
FatalException(env->isolate(), try_catch);
214-
UNREACHABLE();
215-
}
200+
FatalTryCatch try_catch(env);
201+
fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)
202+
.FromMaybe(Local<Value>());
216203
}
217204

218205

@@ -241,14 +228,9 @@ void AsyncWrap::EmitAfter(Environment* env, double async_id) {
241228
// end of _fatalException().
242229
Local<Value> async_id_value = Number::New(env->isolate(), async_id);
243230
Local<Function> fn = env->async_hooks_after_function();
244-
TryCatch try_catch(env->isolate());
245-
MaybeLocal<Value> ar = fn->Call(
246-
env->context(), Undefined(env->isolate()), 1, &async_id_value);
247-
if (ar.IsEmpty()) {
248-
ClearFatalExceptionHandlers(env);
249-
FatalException(env->isolate(), try_catch);
250-
UNREACHABLE();
251-
}
231+
FatalTryCatch try_catch(env);
232+
fn->Call(env->context(), Undefined(env->isolate()), 1, &async_id_value)
233+
.FromMaybe(Local<Value>());
252234
}
253235

254236
class PromiseWrap : public AsyncWrap {
@@ -748,14 +730,9 @@ void AsyncWrap::EmitAsyncInit(Environment* env,
748730
object,
749731
};
750732

751-
TryCatch try_catch(env->isolate());
752-
MaybeLocal<Value> ret = init_fn->Call(
753-
env->context(), object, arraysize(argv), argv);
754-
755-
if (ret.IsEmpty()) {
756-
ClearFatalExceptionHandlers(env);
757-
FatalException(env->isolate(), try_catch);
758-
}
733+
FatalTryCatch try_catch(env);
734+
init_fn->Call(env->context(), object, arraysize(argv), argv)
735+
.FromMaybe(Local<Value>());
759736
}
760737

761738

src/node.cc

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1471,6 +1471,8 @@ void AppendExceptionLine(Environment* env,
14711471
static void ReportException(Environment* env,
14721472
Local<Value> er,
14731473
Local<Message> message) {
1474+
CHECK(!er.IsEmpty());
1475+
CHECK(!message.IsEmpty());
14741476
HandleScope scope(env->isolate());
14751477

14761478
AppendExceptionLine(env, er, message, FATAL_ERROR);
@@ -1540,6 +1542,10 @@ static void ReportException(Environment* env,
15401542
}
15411543

15421544
fflush(stderr);
1545+
1546+
#if HAVE_INSPECTOR
1547+
env->inspector_agent()->FatalException(er, message);
1548+
#endif
15431549
}
15441550

15451551

@@ -2399,6 +2405,15 @@ NO_RETURN void FatalError(const char* location, const char* message) {
23992405
}
24002406

24012407

2408+
FatalTryCatch::~FatalTryCatch() {
2409+
if (HasCaught()) {
2410+
HandleScope scope(env_->isolate());
2411+
ReportException(env_, *this);
2412+
exit(7);
2413+
}
2414+
}
2415+
2416+
24022417
void FatalException(Isolate* isolate,
24032418
Local<Value> error,
24042419
Local<Message> message) {
@@ -2441,9 +2456,6 @@ void FatalException(Isolate* isolate,
24412456
}
24422457

24432458
if (exit_code) {
2444-
#if HAVE_INSPECTOR
2445-
env->inspector_agent()->FatalException(error, message);
2446-
#endif
24472459
exit(exit_code);
24482460
}
24492461
}
@@ -2463,25 +2475,6 @@ static void OnMessage(Local<Message> message, Local<Value> error) {
24632475
FatalException(Isolate::GetCurrent(), error, message);
24642476
}
24652477

2466-
2467-
void ClearFatalExceptionHandlers(Environment* env) {
2468-
Local<Object> process = env->process_object();
2469-
Local<Value> events =
2470-
process->Get(env->context(), env->events_string()).ToLocalChecked();
2471-
2472-
if (events->IsObject()) {
2473-
events.As<Object>()->Set(
2474-
env->context(),
2475-
OneByteString(env->isolate(), "uncaughtException"),
2476-
Undefined(env->isolate())).FromJust();
2477-
}
2478-
2479-
process->Set(
2480-
env->context(),
2481-
env->domain_string(),
2482-
Undefined(env->isolate())).FromJust();
2483-
}
2484-
24852478
// Call process.emitWarning(str), fmt is a snprintf() format string
24862479
void ProcessEmitWarning(Environment* env, const char* fmt, ...) {
24872480
char warning[1024];

src/node_internals.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,17 @@ void AppendExceptionLine(Environment* env,
277277

278278
NO_RETURN void FatalError(const char* location, const char* message);
279279

280+
// Like a `TryCatch` but exits the process if an exception was caught.
281+
class FatalTryCatch : public v8::TryCatch {
282+
public:
283+
explicit FatalTryCatch(Environment* env)
284+
: TryCatch(env->isolate()), env_(env) {}
285+
~FatalTryCatch();
286+
287+
private:
288+
Environment* env_;
289+
};
290+
280291
void ProcessEmitWarning(Environment* env, const char* fmt, ...);
281292

282293
void FillStatsArray(double* fields, const uv_stat_t* s);
@@ -330,11 +341,6 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
330341
uint32_t zero_fill_field_ = 1; // Boolean but exposed as uint32 to JS land.
331342
};
332343

333-
// Clear any domain and/or uncaughtException handlers to force the error's
334-
// propagation and shutdown the process. Use this to force the process to exit
335-
// by clearing all callbacks that could handle the error.
336-
void ClearFatalExceptionHandlers(Environment* env);
337-
338344
namespace Buffer {
339345
v8::MaybeLocal<v8::Object> Copy(Environment* env, const char* data, size_t len);
340346
v8::MaybeLocal<v8::Object> New(Environment* env, size_t size);

src/node_url.cc

Lines changed: 10 additions & 13 deletions
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)