diff options
author | Trevor Norris <trev.norris@gmail.com> | 2014-12-09 05:10:44 +0100 |
---|---|---|
committer | Bert Belder <bertbelder@gmail.com> | 2014-12-09 17:57:18 +0100 |
commit | b9e6032d0ea2774413144857521f7f2613010d2e (patch) | |
tree | 7bd5856aecd9a4e7ec7e4457a084ec92685c3118 /src/async-wrap-inl.h | |
parent | bd83c3966d4564709e8449b3c699af6ece27ff12 (diff) | |
download | node-new-b9e6032d0ea2774413144857521f7f2613010d2e.tar.gz |
async-wrap: add event hooks
Call a user-defined callback at specific points in the lifetime of an
asynchronous event. Which are on instantiation, just before/after the
callback has been run.
**If any of these callbacks throws an exception, there is no forgiveness
or recovery. A message will be displayed and a core file dumped.**
Currently these only tie into AsyncWrap, meaning no call to a hook
callback will be made for timers or process.nextTick() events. Though
those will be added in a future commit.
Here are a few notes on how to make the hooks work:
- The "this" of all event hook callbacks is the request object.
- The zero field (kCallInitHook) of the flags object passed to
setupHooks() must be set != 0 before the init callback will be called.
- kCallInitHook only affects the calling of the init callback. If the
request object has been run through the create callback it will always
run the before/after callbacks. Regardless of kCallInitHook.
- In the init callback the property "_asyncQueue" must be attached to
the request object. e.g.
function initHook() {
this._asyncQueue = {};
}
- DO NOT inspect the properties of the object in the init callback.
Since the object is in the middle of being instantiated there are some
cases when a getter is not complete, and doing so will cause Node to
crash.
PR-URL: https://github.com/joyent/node/pull/8110
Signed-off-by: Trevor Norris <trev.norris@gmail.com>
Reviewed-by: Fedor Indutny <fedor@indutny.com>
Reviewed-by: Alexis Campailla <alexis@janeasystems.com>
Reviewed-by: Julien Gilli <julien.gilli@joyent.com>
Diffstat (limited to 'src/async-wrap-inl.h')
-rw-r--r-- | src/async-wrap-inl.h | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/async-wrap-inl.h b/src/async-wrap-inl.h index 73a177872e..4dbb3a6cfc 100644 --- a/src/async-wrap-inl.h +++ b/src/async-wrap-inl.h @@ -27,6 +27,7 @@ #include "base-object-inl.h" #include "env.h" #include "env-inl.h" +#include "node_internals.h" #include "util.h" #include "util-inl.h" #include "v8.h" @@ -38,7 +39,42 @@ inline AsyncWrap::AsyncWrap(Environment* env, ProviderType provider, AsyncWrap* parent) : BaseObject(env, object), + has_async_queue_(false), provider_type_(provider) { + // Check user controlled flag to see if the init callback should run. + if (!env->call_async_init_hook()) + return; + + // TODO(trevnorris): Until it's verified all passed object's are not weak, + // add a HandleScope to make sure there's no leak. + v8::HandleScope scope(env->isolate()); + + v8::Local<v8::Object> parent_obj; + + v8::TryCatch try_catch; + + // If a parent value was sent then call its pre/post functions to let it know + // a conceptual "child" is being instantiated (e.g. that a server has + // received a connection). + if (parent != nullptr) { + parent_obj = parent->object(); + env->async_hooks_pre_function()->Call(parent_obj, 0, nullptr); + if (try_catch.HasCaught()) + FatalError("node::AsyncWrap::AsyncWrap", "parent pre hook threw"); + } + + env->async_hooks_init_function()->Call(object, 0, nullptr); + + if (try_catch.HasCaught()) + FatalError("node::AsyncWrap::AsyncWrap", "init hook threw"); + + has_async_queue_ = true; + + if (parent != nullptr) { + env->async_hooks_post_function()->Call(parent_obj, 0, nullptr); + if (try_catch.HasCaught()) + FatalError("node::AsyncWrap::AsyncWrap", "parent post hook threw"); + } } |