diff --git a/src/env-inl.h b/src/env-inl.h index 6d7520dab0acc8..526ddefd447ce8 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -305,6 +305,10 @@ inline Environment* Environment::GetCurrent( info.Data().template As()->Value()); } +inline Environment* Environment::GetThreadLocalEnv() { + return static_cast(uv_key_get(&thread_local_env)); +} + inline Environment::Environment(IsolateData* isolate_data, v8::Local context) : isolate_(context->GetIsolate()), diff --git a/src/env.cc b/src/env.cc index 960cc4d5f88a69..7d91c243aefcca 100644 --- a/src/env.cc +++ b/src/env.cc @@ -75,6 +75,11 @@ v8::CpuProfiler* IsolateData::GetCpuProfiler() { return cpu_profiler_; } + +void InitThreadLocalOnce() { + CHECK_EQ(0, uv_key_create(&Environment::thread_local_env)); +} + void Environment::Start(int argc, const char* const* argv, int exec_argc, @@ -142,6 +147,10 @@ void Environment::Start(int argc, SetupProcessObject(this, argc, argv, exec_argc, exec_argv); LoadAsyncWrapperInfo(this); + + static uv_once_t init_once = UV_ONCE_INIT; + uv_once(&init_once, InitThreadLocalOnce); + uv_key_set(&thread_local_env, this); } void Environment::CleanupHandles() { @@ -373,4 +382,6 @@ void Environment::AsyncHooks::grow_async_ids_stack() { async_ids_stack_.GetJSArray()).FromJust(); } +uv_key_t Environment::thread_local_env = {}; + } // namespace node diff --git a/src/env.h b/src/env.h index 8e0cf61a4a57ab..05fee43e9bd391 100644 --- a/src/env.h +++ b/src/env.h @@ -563,6 +563,9 @@ class Environment { static inline Environment* GetCurrent( const v8::PropertyCallbackInfo& info); + static uv_key_t thread_local_env; + static inline Environment* GetThreadLocalEnv(); + inline Environment(IsolateData* isolate_data, v8::Local context); inline ~Environment(); diff --git a/src/node.cc b/src/node.cc index 737f589eaad01c..5f6c7f266306b8 100644 --- a/src/node.cc +++ b/src/node.cc @@ -4646,11 +4646,8 @@ uv_loop_t* GetCurrentEventLoop(v8::Isolate* isolate) { } -static uv_key_t thread_local_env; - - void AtExit(void (*cb)(void* arg), void* arg) { - auto env = static_cast(uv_key_get(&thread_local_env)); + auto env = Environment::GetThreadLocalEnv(); AtExit(env, cb, arg); } @@ -4781,8 +4778,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data, Local context = NewContext(isolate); Context::Scope context_scope(context); Environment env(isolate_data, context); - CHECK_EQ(0, uv_key_create(&thread_local_env)); - uv_key_set(&thread_local_env, &env); env.Start(argc, argv, exec_argc, exec_argv, v8_is_profiling); const char* path = argc > 1 ? argv[1] : nullptr; @@ -4832,7 +4827,6 @@ inline int Start(Isolate* isolate, IsolateData* isolate_data, const int exit_code = EmitExit(&env); RunAtExit(&env); - uv_key_delete(&thread_local_env); v8_platform.DrainVMTasks(isolate); v8_platform.CancelVMTasks(isolate); diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc index 4575d3b65ae318..19641ef3ac5cd0 100644 --- a/test/cctest/test_environment.cc +++ b/test/cctest/test_environment.cc @@ -39,6 +39,16 @@ TEST_F(EnvironmentTest, AtExitWithEnvironment) { EXPECT_TRUE(called_cb_1); } +TEST_F(EnvironmentTest, AtExitWithoutEnvironment) { + const v8::HandleScope handle_scope(isolate_); + const Argv argv; + Env env {handle_scope, argv}; + + AtExit(at_exit_callback1); // No Environment is passed to AtExit. + RunAtExit(*env); + EXPECT_TRUE(called_cb_1); +} + TEST_F(EnvironmentTest, AtExitWithArgument) { const v8::HandleScope handle_scope(isolate_); const Argv argv;