diff --git a/src/async-wrap.cc b/src/async-wrap.cc index 29ea139f5f91c0..01dcaf277c1840 100644 --- a/src/async-wrap.cc +++ b/src/async-wrap.cc @@ -184,6 +184,8 @@ Local AsyncWrap::MakeCallback(const Local cb, Local domain; bool has_domain = false; + Environment::AsyncCallbackScope callback_scope(env()); + if (env()->using_domains()) { Local domain_v = context->Get(env()->domain_string()); has_domain = domain_v->IsObject(); @@ -236,7 +238,7 @@ Local AsyncWrap::MakeCallback(const Local cb, Environment::TickInfo* tick_info = env()->tick_info(); - if (tick_info->in_tick()) { + if (callback_scope.in_makecallback()) { return ret; } @@ -249,12 +251,8 @@ Local AsyncWrap::MakeCallback(const Local cb, return ret; } - tick_info->set_in_tick(true); - env()->tick_callback_function()->Call(process, 0, nullptr); - tick_info->set_in_tick(false); - if (try_catch.HasCaught()) { tick_info->set_last_threw(true); return Undefined(env()->isolate()); diff --git a/src/env-inl.h b/src/env-inl.h index f73e9c6ba2000a..eebb68eb463e93 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -88,6 +88,20 @@ inline void Environment::AsyncHooks::set_enable_callbacks(uint32_t flag) { fields_[kEnableCallbacks] = flag; } +inline Environment::AsyncCallbackScope::AsyncCallbackScope(Environment* env) + : env_(env) { + env_->makecallback_cntr_++; +} + +inline Environment::AsyncCallbackScope::~AsyncCallbackScope() { + env_->makecallback_cntr_--; + CHECK_GE(env_->makecallback_cntr_, 0); +} + +inline bool Environment::AsyncCallbackScope::in_makecallback() { + return env_->makecallback_cntr_ > 1; +} + inline Environment::DomainFlag::DomainFlag() { for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0; } @@ -210,6 +224,7 @@ inline Environment::Environment(v8::Local context, using_domains_(false), printed_error_(false), trace_sync_io_(false), + makecallback_cntr_(0), async_wrap_uid_(0), debugger_agent_(this), http_parser_buffer_(nullptr), diff --git a/src/env.cc b/src/env.cc index e28866efd06894..8fa6e5c43afe06 100644 --- a/src/env.cc +++ b/src/env.cc @@ -57,10 +57,10 @@ void Environment::PrintSyncTrace() const { } -bool Environment::KickNextTick() { +bool Environment::KickNextTick(Environment::AsyncCallbackScope* scope) { TickInfo* info = tick_info(); - if (info->in_tick()) { + if (scope->in_makecallback()) { return true; } @@ -73,15 +73,11 @@ bool Environment::KickNextTick() { return true; } - info->set_in_tick(true); - // process nextTicks after call TryCatch try_catch; try_catch.SetVerbose(true); tick_callback_function()->Call(process_object(), 0, nullptr); - info->set_in_tick(false); - if (try_catch.HasCaught()) { info->set_last_threw(true); return false; diff --git a/src/env.h b/src/env.h index 1531d9911e310b..8ae681ff43c86f 100644 --- a/src/env.h +++ b/src/env.h @@ -294,6 +294,19 @@ class Environment { DISALLOW_COPY_AND_ASSIGN(AsyncHooks); }; + class AsyncCallbackScope { + public: + explicit AsyncCallbackScope(Environment* env); + ~AsyncCallbackScope(); + + inline bool in_makecallback(); + + private: + Environment* env_; + + DISALLOW_COPY_AND_ASSIGN(AsyncCallbackScope); + }; + class DomainFlag { public: inline uint32_t* fields(); @@ -446,7 +459,7 @@ class Environment { inline int64_t get_async_wrap_uid(); - bool KickNextTick(); + bool KickNextTick(AsyncCallbackScope* scope); inline uint32_t* heap_statistics_buffer() const; inline void set_heap_statistics_buffer(uint32_t* pointer); @@ -541,6 +554,7 @@ class Environment { bool using_domains_; bool printed_error_; bool trace_sync_io_; + size_t makecallback_cntr_; int64_t async_wrap_uid_; debugger::Agent debugger_agent_; diff --git a/src/node.cc b/src/node.cc index b048166cd9d8df..ef59a103c30eac 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1132,6 +1132,8 @@ Local MakeCallback(Environment* env, bool ran_init_callback = false; bool has_domain = false; + Environment::AsyncCallbackScope callback_scope(env); + // TODO(trevnorris): Adding "_asyncQueue" to the "this" in the init callback // is a horrible way to detect usage. Rethink how detection should happen. if (recv->IsObject()) { @@ -1192,7 +1194,7 @@ Local MakeCallback(Environment* env, } } - if (!env->KickNextTick()) + if (!env->KickNextTick(&callback_scope)) return Undefined(env->isolate()); return ret; @@ -4100,7 +4102,10 @@ static void StartNodeInstance(void* arg) { if (instance_data->use_debug_agent()) StartDebug(env, debug_wait_connect); - LoadEnvironment(env); + { + Environment::AsyncCallbackScope callback_scope(env); + LoadEnvironment(env); + } env->set_trace_sync_io(trace_sync_io); diff --git a/src/node_http_parser.cc b/src/node_http_parser.cc index 8c976b2e9f0b4c..c6254d57c840ed 100644 --- a/src/node_http_parser.cc +++ b/src/node_http_parser.cc @@ -579,6 +579,8 @@ class Parser : public BaseObject { if (!cb->IsFunction()) return; + Environment::AsyncCallbackScope callback_scope(parser->env()); + // Hooks for GetCurrentBuffer parser->current_buffer_len_ = nread; parser->current_buffer_data_ = buf->base; @@ -588,7 +590,7 @@ class Parser : public BaseObject { parser->current_buffer_len_ = 0; parser->current_buffer_data_ = nullptr; - parser->env()->KickNextTick(); + parser->env()->KickNextTick(&callback_scope); } diff --git a/src/node_internals.h b/src/node_internals.h index 3df7676d2a9d51..6e3f7204777835 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -69,8 +69,6 @@ v8::Local MakeCallback(Environment* env, int argc = 0, v8::Local* argv = nullptr); -bool KickNextTick(); - // Convert a struct sockaddr to a { address: '1.2.3.4', port: 1234 } JS object. // Sets address and port properties on the info object and returns it. // If |info| is omitted, a new object is returned.