summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTrevor Norris <trev.norris@gmail.com>2016-03-14 12:35:22 -0600
committerTrevor Norris <trev.norris@gmail.com>2016-03-28 11:32:54 -0600
commita17200b520919a20f72b3353974de82684168b35 (patch)
tree10e95fe36c514940ac7cc5b8e0547434220b0ce1 /src
parent20337addd6ad134f61684708754be691a3f2ec98 (diff)
downloadandroid-node-v8-a17200b520919a20f72b3353974de82684168b35.tar.gz
android-node-v8-a17200b520919a20f72b3353974de82684168b35.tar.bz2
android-node-v8-a17200b520919a20f72b3353974de82684168b35.zip
async_wrap: don't abort on callback exception
Rather than abort if the init/pre/post/final/destroy callbacks throw, force the exception to propagate and not be made catchable. This way the application is still not allowed to proceed but also allowed the location of the failure to print before exiting. Though the stack itself may not be of much use since all callbacks except init are called from the bottom of the call stack. /tmp/async-test.js:14 throw new Error('pre'); ^ Error: pre at InternalFieldObject.pre (/tmp/async-test.js:14:9) PR-URL: https://github.com/nodejs/node/pull/5756 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Andreas Madsen <amwebdk@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/async-wrap-inl.h15
-rw-r--r--src/async-wrap.cc20
-rw-r--r--src/node.cc38
-rw-r--r--src/node_internals.h5
4 files changed, 66 insertions, 12 deletions
diff --git a/src/async-wrap-inl.h b/src/async-wrap-inl.h
index e6b24af7fd..e61e2ad4bf 100644
--- a/src/async-wrap-inl.h
+++ b/src/async-wrap-inl.h
@@ -51,11 +51,15 @@ inline AsyncWrap::AsyncWrap(Environment* env,
argv[3] = parent->object();
}
+ v8::TryCatch try_catch(env->isolate());
+
v8::MaybeLocal<v8::Value> ret =
init_fn->Call(env->context(), object, ARRAY_SIZE(argv), argv);
- if (ret.IsEmpty())
- FatalError("node::AsyncWrap::AsyncWrap", "init hook threw");
+ if (ret.IsEmpty()) {
+ ClearFatalExceptionHandlers(env);
+ FatalException(env->isolate(), try_catch);
+ }
bits_ |= 1; // ran_init_callback() is true now.
}
@@ -69,10 +73,13 @@ inline AsyncWrap::~AsyncWrap() {
if (!fn.IsEmpty()) {
v8::HandleScope scope(env()->isolate());
v8::Local<v8::Value> uid = v8::Integer::New(env()->isolate(), get_uid());
+ v8::TryCatch try_catch(env()->isolate());
v8::MaybeLocal<v8::Value> ret =
fn->Call(env()->context(), v8::Null(env()->isolate()), 1, &uid);
- if (ret.IsEmpty())
- FatalError("node::AsyncWrap::~AsyncWrap", "destroy hook threw");
+ if (ret.IsEmpty()) {
+ ClearFatalExceptionHandlers(env());
+ FatalException(env()->isolate(), try_catch);
+ }
}
}
diff --git a/src/async-wrap.cc b/src/async-wrap.cc
index db9d0a4f35..05ee7fa02a 100644
--- a/src/async-wrap.cc
+++ b/src/async-wrap.cc
@@ -18,6 +18,7 @@ using v8::HeapProfiler;
using v8::Integer;
using v8::Isolate;
using v8::Local;
+using v8::MaybeLocal;
using v8::Object;
using v8::RetainedObjectInfo;
using v8::TryCatch;
@@ -225,8 +226,13 @@ Local<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
}
if (ran_init_callback() && !pre_fn.IsEmpty()) {
- if (pre_fn->Call(context, 1, &uid).IsEmpty())
- FatalError("node::AsyncWrap::MakeCallback", "pre hook threw");
+ TryCatch try_catch(env()->isolate());
+ MaybeLocal<Value> ar = pre_fn->Call(env()->context(), context, 1, &uid);
+ if (ar.IsEmpty()) {
+ ClearFatalExceptionHandlers(env());
+ FatalException(env()->isolate(), try_catch);
+ return Local<Value>();
+ }
}
Local<Value> ret = cb->Call(context, argc, argv);
@@ -234,8 +240,14 @@ Local<Value> AsyncWrap::MakeCallback(const Local<Function> cb,
if (ran_init_callback() && !post_fn.IsEmpty()) {
Local<Value> did_throw = Boolean::New(env()->isolate(), ret.IsEmpty());
Local<Value> vals[] = { uid, did_throw };
- if (post_fn->Call(context, ARRAY_SIZE(vals), vals).IsEmpty())
- FatalError("node::AsyncWrap::MakeCallback", "post hook threw");
+ TryCatch try_catch(env()->isolate());
+ MaybeLocal<Value> ar =
+ post_fn->Call(env()->context(), context, ARRAY_SIZE(vals), vals);
+ if (ar.IsEmpty()) {
+ ClearFatalExceptionHandlers(env());
+ FatalException(env()->isolate(), try_catch);
+ return Local<Value>();
+ }
}
if (ret.IsEmpty()) {
diff --git a/src/node.cc b/src/node.cc
index 83a4110504..fa9c3626aa 100644
--- a/src/node.cc
+++ b/src/node.cc
@@ -1193,8 +1193,13 @@ Local<Value> MakeCallback(Environment* env,
}
if (ran_init_callback && !pre_fn.IsEmpty()) {
- if (pre_fn->Call(object, 0, nullptr).IsEmpty())
- FatalError("node::MakeCallback", "pre hook threw");
+ TryCatch try_catch(env->isolate());
+ MaybeLocal<Value> ar = pre_fn->Call(env->context(), object, 0, nullptr);
+ if (ar.IsEmpty()) {
+ ClearFatalExceptionHandlers(env);
+ FatalException(env->isolate(), try_catch);
+ return Local<Value>();
+ }
}
Local<Value> ret = callback->Call(recv, argc, argv);
@@ -1205,8 +1210,14 @@ Local<Value> MakeCallback(Environment* env,
// This needs to be fixed.
Local<Value> vals[] =
{ Undefined(env->isolate()).As<Value>(), did_throw };
- if (post_fn->Call(object, ARRAY_SIZE(vals), vals).IsEmpty())
- FatalError("node::MakeCallback", "post hook threw");
+ TryCatch try_catch(env->isolate());
+ MaybeLocal<Value> ar =
+ post_fn->Call(env->context(), object, ARRAY_SIZE(vals), vals);
+ if (ar.IsEmpty()) {
+ ClearFatalExceptionHandlers(env);
+ FatalException(env->isolate(), try_catch);
+ return Local<Value>();
+ }
}
if (ret.IsEmpty()) {
@@ -2404,6 +2415,25 @@ void OnMessage(Local<Message> message, Local<Value> error) {
}
+void ClearFatalExceptionHandlers(Environment* env) {
+ Local<Object> process = env->process_object();
+ Local<Value> events =
+ process->Get(env->context(), env->events_string()).ToLocalChecked();
+
+ if (events->IsObject()) {
+ events.As<Object>()->Set(
+ env->context(),
+ OneByteString(env->isolate(), "uncaughtException"),
+ Undefined(env->isolate())).FromJust();
+ }
+
+ process->Set(
+ env->context(),
+ env->domain_string(),
+ Undefined(env->isolate())).FromJust();
+}
+
+
static void Binding(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
diff --git a/src/node_internals.h b/src/node_internals.h
index 24072e0717..b62c5ff8d5 100644
--- a/src/node_internals.h
+++ b/src/node_internals.h
@@ -236,6 +236,11 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
Environment* env_;
};
+// Clear any domain and/or uncaughtException handlers to force the error's
+// propagation and shutdown the process. Use this to force the process to exit
+// by clearing all callbacks that could handle the error.
+void ClearFatalExceptionHandlers(Environment* env);
+
enum NodeInstanceType { MAIN, WORKER };
class NodeInstanceData {