summaryrefslogtreecommitdiff
path: root/src/async-wrap-inl.h
diff options
context:
space:
mode:
authorTrevor Norris <trev.norris@gmail.com>2014-12-09 05:10:44 +0100
committerBert Belder <bertbelder@gmail.com>2014-12-09 17:57:18 +0100
commitb9e6032d0ea2774413144857521f7f2613010d2e (patch)
tree7bd5856aecd9a4e7ec7e4457a084ec92685c3118 /src/async-wrap-inl.h
parentbd83c3966d4564709e8449b3c699af6ece27ff12 (diff)
downloadnode-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.h36
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");
+ }
}