Skip to content

Commit 3814534

Browse files
rpetrichGabriel Schulhof
authored andcommitted
src: fix race on modpending
Fixes a rare race condition on modpending when two native modules are loaded simultaneously on different threads by storing it thread- locally. PR-URL: #21611 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]>
1 parent 73b8dde commit 3814534

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

src/node.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ static int v8_thread_pool_size = v8_default_thread_pool_size;
187187
static bool prof_process = false;
188188
static bool v8_is_profiling = false;
189189
static bool node_is_initialized = false;
190-
static node_module* modpending;
190+
static uv_once_t init_modpending_once = UV_ONCE_INIT;
191+
static uv_key_t thread_local_modpending;
191192
static node_module* modlist_builtin;
192193
static node_module* modlist_internal;
193194
static node_module* modlist_linked;
@@ -1253,7 +1254,7 @@ extern "C" void node_module_register(void* m) {
12531254
mp->nm_link = modlist_linked;
12541255
modlist_linked = mp;
12551256
} else {
1256-
modpending = mp;
1257+
uv_key_set(&thread_local_modpending, mp);
12571258
}
12581259
}
12591260

@@ -1367,6 +1368,10 @@ inline napi_addon_register_func GetNapiInitializerCallback(DLib* dlib) {
13671368
reinterpret_cast<napi_addon_register_func>(dlib->GetSymbolAddress(name));
13681369
}
13691370

1371+
void InitModpendingOnce() {
1372+
CHECK_EQ(0, uv_key_create(&thread_local_modpending));
1373+
}
1374+
13701375
// DLOpen is process.dlopen(module, filename, flags).
13711376
// Used to load 'module.node' dynamically shared objects.
13721377
//
@@ -1377,7 +1382,8 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
13771382
Environment* env = Environment::GetCurrent(args);
13781383
auto context = env->context();
13791384

1380-
CHECK_NULL(modpending);
1385+
uv_once(&init_modpending_once, InitModpendingOnce);
1386+
CHECK_NULL(uv_key_get(&thread_local_modpending));
13811387

13821388
if (args.Length() < 2) {
13831389
env->ThrowError("process.dlopen needs at least 2 arguments.");
@@ -1405,8 +1411,9 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
14051411
// Objects containing v14 or later modules will have registered themselves
14061412
// on the pending list. Activate all of them now. At present, only one
14071413
// module per object is supported.
1408-
node_module* const mp = modpending;
1409-
modpending = nullptr;
1414+
node_module* const mp = static_cast<node_module*>(
1415+
uv_key_get(&thread_local_modpending));
1416+
uv_key_set(&thread_local_modpending, nullptr);
14101417

14111418
if (!is_opened) {
14121419
Local<String> errmsg = OneByteString(env->isolate(), dlib.errmsg_.c_str());

0 commit comments

Comments
 (0)