Skip to content

Commit c2fee5d

Browse files
ofrobotsjasnell
authored andcommitted
src: ready background workers before bootstrap
Make sure background workers are ready before proceeding with the bootstrap or post-bootstrap execution of any code that may trigger `process.exit()`. Fixes: #23065 PR-URL: #23233 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
1 parent 4bd935e commit c2fee5d

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

src/node_platform.cc

+35-2
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,29 @@ using v8::TracingController;
1818

1919
namespace {
2020

21+
struct PlatformWorkerData {
22+
TaskQueue<Task>* task_queue;
23+
Mutex* platform_workers_mutex;
24+
ConditionVariable* platform_workers_ready;
25+
int* pending_platform_workers;
26+
int id;
27+
};
28+
2129
static void PlatformWorkerThread(void* data) {
30+
std::unique_ptr<PlatformWorkerData>
31+
worker_data(static_cast<PlatformWorkerData*>(data));
32+
33+
TaskQueue<Task>* pending_worker_tasks = worker_data->task_queue;
2234
TRACE_EVENT_METADATA1("__metadata", "thread_name", "name",
2335
"PlatformWorkerThread");
24-
TaskQueue<Task>* pending_worker_tasks = static_cast<TaskQueue<Task>*>(data);
36+
37+
// Notify the main thread that the platform worker is ready.
38+
{
39+
Mutex::ScopedLock lock(*worker_data->platform_workers_mutex);
40+
(*worker_data->pending_platform_workers)--;
41+
worker_data->platform_workers_ready->Signal(lock);
42+
}
43+
2544
while (std::unique_ptr<Task> task = pending_worker_tasks->BlockingPop()) {
2645
task->Run();
2746
pending_worker_tasks->NotifyOfCompletion();
@@ -148,17 +167,31 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
148167
};
149168

150169
WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(int thread_pool_size) {
170+
Mutex::ScopedLock lock(platform_workers_mutex_);
171+
pending_platform_workers_ = thread_pool_size;
172+
151173
delayed_task_scheduler_.reset(
152174
new DelayedTaskScheduler(&pending_worker_tasks_));
153175
threads_.push_back(delayed_task_scheduler_->Start());
176+
154177
for (int i = 0; i < thread_pool_size; i++) {
178+
PlatformWorkerData* worker_data = new PlatformWorkerData{
179+
&pending_worker_tasks_, &platform_workers_mutex_,
180+
&platform_workers_ready_, &pending_platform_workers_, i
181+
};
155182
std::unique_ptr<uv_thread_t> t { new uv_thread_t() };
156183
if (uv_thread_create(t.get(), PlatformWorkerThread,
157-
&pending_worker_tasks_) != 0) {
184+
worker_data) != 0) {
158185
break;
159186
}
160187
threads_.push_back(std::move(t));
161188
}
189+
190+
// Wait for platform workers to initialize before continuing with the
191+
// bootstrap.
192+
while (pending_platform_workers_ > 0) {
193+
platform_workers_ready_.Wait(lock);
194+
}
162195
}
163196

164197
void WorkerThreadsTaskRunner::PostTask(std::unique_ptr<Task> task) {

src/node_platform.h

+4
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ class WorkerThreadsTaskRunner {
116116
std::unique_ptr<DelayedTaskScheduler> delayed_task_scheduler_;
117117

118118
std::vector<std::unique_ptr<uv_thread_t>> threads_;
119+
120+
Mutex platform_workers_mutex_;
121+
ConditionVariable platform_workers_ready_;
122+
int pending_platform_workers_;
119123
};
120124

121125
class NodePlatform : public MultiIsolatePlatform {

0 commit comments

Comments
 (0)