src: align worker and main thread code with embedder API · nodejs/node@808dedc · GitHub
Skip to content

Commit 808dedc

Browse files
committed
src: align worker and main thread code with embedder API
This addresses some long-standing TODOs by Joyee and me about making the embedder API more powerful and us less reliant on internal APIs for creating the main thread and Workers. Backport-PR-URL: #35241 PR-URL: #30467 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>
1 parent e809a5c commit 808dedc

11 files changed

Lines changed: 253 additions & 115 deletions

src/api/environment.cc

Lines changed: 84 additions & 6 deletions

src/env-inl.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,8 +813,9 @@ void Environment::SetImmediateThreadsafe(Fn&& cb, CallbackFlags::Flags flags) {
813813
{
814814
Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
815815
native_immediates_threadsafe_.Push(std::move(callback));
816+
if (task_queues_async_initialized_)
817+
uv_async_send(&task_queues_async_);
816818
}
817-
uv_async_send(&task_queues_async_);
818819
}
819820

820821
template <typename Fn>
@@ -824,8 +825,9 @@ void Environment::RequestInterrupt(Fn&& cb) {
824825
{
825826
Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
826827
native_immediates_interrupts_.Push(std::move(callback));
828+
if (task_queues_async_initialized_)
829+
uv_async_send(&task_queues_async_);
827830
}
828-
uv_async_send(&task_queues_async_);
829831
RequestInterruptFromV8();
830832
}
831833

@@ -858,11 +860,11 @@ inline bool Environment::is_main_thread() const {
858860
}
859861

860862
inline bool Environment::owns_process_state() const {
861-
return flags_ & kOwnsProcessState;
863+
return flags_ & EnvironmentFlags::kOwnsProcessState;
862864
}
863865

864866
inline bool Environment::owns_inspector() const {
865-
return flags_ & kOwnsInspector;
867+
return flags_ & EnvironmentFlags::kOwnsInspector;
866868
}
867869

868870
inline uint64_t Environment::thread_id() const {
@@ -1176,6 +1178,7 @@ void Environment::RemoveCleanupHook(void (*fn)(void*), void* arg) {
11761178
inline void Environment::RegisterFinalizationGroupForCleanup(
11771179
v8::Local<v8::FinalizationGroup> group) {
11781180
cleanup_finalization_groups_.emplace_back(isolate(), group);
1181+
DCHECK(task_queues_async_initialized_);
11791182
uv_async_send(&task_queues_async_);
11801183
}
11811184

src/env.cc

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,6 @@ void TrackingTraceStateObserver::UpdateTraceCategoryState() {
257257
USE(cb->Call(env_->context(), Undefined(isolate), arraysize(args), args));
258258
}
259259

260-
static std::atomic<uint64_t> next_thread_id{0};
261-
262-
uint64_t Environment::AllocateThreadId() {
263-
return next_thread_id++;
264-
}
265-
266260
void Environment::CreateProperties() {
267261
HandleScope handle_scope(isolate_);
268262
Local<Context> ctx = context();
@@ -319,8 +313,8 @@ Environment::Environment(IsolateData* isolate_data,
319313
Local<Context> context,
320314
const std::vector<std::string>& args,
321315
const std::vector<std::string>& exec_args,
322-
Flags flags,
323-
uint64_t thread_id)
316+
EnvironmentFlags::Flags flags,
317+
ThreadId thread_id)
324318
: isolate_(context->GetIsolate()),
325319
isolate_data_(isolate_data),
326320
immediate_info_(context->GetIsolate()),
@@ -332,14 +326,23 @@ Environment::Environment(IsolateData* isolate_data,
332326
should_abort_on_uncaught_toggle_(isolate_, 1),
333327
stream_base_state_(isolate_, StreamBase::kNumStreamBaseStateFields),
334328
flags_(flags),
335-
thread_id_(thread_id == kNoThreadId ? AllocateThreadId() : thread_id),
329+
thread_id_(thread_id.id == static_cast<uint64_t>(-1) ?
330+
AllocateEnvironmentThreadId().id : thread_id.id),
336331
fs_stats_field_array_(isolate_, kFsStatsBufferLength),
337332
fs_stats_field_bigint_array_(isolate_, kFsStatsBufferLength),
338333
context_(context->GetIsolate(), context) {
339334
// We'll be creating new objects so make sure we've entered the context.
340335
HandleScope handle_scope(isolate());
341336
Context::Scope context_scope(context);
342337

338+
// Set some flags if only kDefaultFlags was passed. This can make API version
339+
// transitions easier for embedders.
340+
if (flags_ & EnvironmentFlags::kDefaultFlags) {
341+
flags_ = flags_ |
342+
EnvironmentFlags::kOwnsProcessState |
343+
EnvironmentFlags::kOwnsInspector;
344+
}
345+
343346
set_env_vars(per_process::system_environment);
344347
enabled_debug_list_.Parse(this);
345348

@@ -358,6 +361,10 @@ Environment::Environment(IsolateData* isolate_data,
358361

359362
AssignToContext(context, ContextInfo(""));
360363

364+
static uv_once_t init_once = UV_ONCE_INIT;
365+
uv_once(&init_once, InitThreadLocalOnce);
366+
uv_key_set(&thread_local_env, this);
367+
361368
if (tracing::AgentWriterHandle* writer = GetTracingAgentWriter()) {
362369
trace_state_observer_ = std::make_unique<TrackingTraceStateObserver>(this);
363370
if (TracingController* tracing_controller = writer->GetTracingController())
@@ -407,6 +414,9 @@ Environment::Environment(IsolateData* isolate_data,
407414
Environment::~Environment() {
408415
if (interrupt_data_ != nullptr) *interrupt_data_ = nullptr;
409416

417+
// FreeEnvironment() should have set this.
418+
CHECK(is_stopping());
419+
410420
isolate()->GetHeapProfiler()->RemoveBuildEmbedderGraphCallback(
411421
BuildEmbedderGraph, this);
412422

@@ -493,6 +503,15 @@ void Environment::InitializeLibuv(bool start_profiler_idle_notifier) {
493503
uv_unref(reinterpret_cast<uv_handle_t*>(&idle_check_handle_));
494504
uv_unref(reinterpret_cast<uv_handle_t*>(&task_queues_async_));
495505

506+
{
507+
Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
508+
task_queues_async_initialized_ = true;
509+
if (native_immediates_threadsafe_.size() > 0 ||
510+
native_immediates_interrupts_.size() > 0) {
511+
uv_async_send(&task_queues_async_);
512+
}
513+
}
514+
496515
// Register clean-up cb to be called to clean up the handles
497516
// when the environment is freed, note that they are not cleaned in
498517
// the one environment per process setup, but will be called in
@@ -502,10 +521,6 @@ void Environment::InitializeLibuv(bool start_profiler_idle_notifier) {
502521
if (start_profiler_idle_notifier) {
503522
StartProfilerIdleNotifier();
504523
}
505-
506-
static uv_once_t init_once = UV_ONCE_INIT;
507-
uv_once(&init_once, InitThreadLocalOnce);
508-
uv_key_set(&thread_local_env, this);
509524
}
510525

511526
void Environment::ExitEnv() {
@@ -539,6 +554,11 @@ void Environment::RegisterHandleCleanups() {
539554
}
540555

541556
void Environment::CleanupHandles() {
557+
{
558+
Mutex::ScopedLock lock(native_immediates_threadsafe_mutex_);
559+
task_queues_async_initialized_ = false;
560+
}
561+
542562
Isolate::DisallowJavascriptExecutionScope disallow_js(isolate(),
543563
Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
544564

@@ -1103,6 +1123,7 @@ void Environment::CleanupFinalizationGroups() {
11031123
if (try_catch.HasCaught() && !try_catch.HasTerminated())
11041124
errors::TriggerUncaughtException(isolate(), try_catch);
11051125
// Re-schedule the execution of the remainder of the queue.
1126+
CHECK(task_queues_async_initialized_);
11061127
uv_async_send(&task_queues_async_);
11071128
return;
11081129
}

src/env.h

Lines changed: 8 additions & 12 deletions

0 commit comments

Comments
 (0)