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: https://github.com/nodejs/node/pull/21611 Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
This commit is contained in:
parent
73b8ddee04
commit
38145344f1
17
src/node.cc
17
src/node.cc
@ -187,7 +187,8 @@ static int v8_thread_pool_size = v8_default_thread_pool_size;
|
|||||||
static bool prof_process = false;
|
static bool prof_process = false;
|
||||||
static bool v8_is_profiling = false;
|
static bool v8_is_profiling = false;
|
||||||
static bool node_is_initialized = false;
|
static bool node_is_initialized = false;
|
||||||
static node_module* modpending;
|
static uv_once_t init_modpending_once = UV_ONCE_INIT;
|
||||||
|
static uv_key_t thread_local_modpending;
|
||||||
static node_module* modlist_builtin;
|
static node_module* modlist_builtin;
|
||||||
static node_module* modlist_internal;
|
static node_module* modlist_internal;
|
||||||
static node_module* modlist_linked;
|
static node_module* modlist_linked;
|
||||||
@ -1253,7 +1254,7 @@ extern "C" void node_module_register(void* m) {
|
|||||||
mp->nm_link = modlist_linked;
|
mp->nm_link = modlist_linked;
|
||||||
modlist_linked = mp;
|
modlist_linked = mp;
|
||||||
} else {
|
} else {
|
||||||
modpending = mp;
|
uv_key_set(&thread_local_modpending, mp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1367,6 +1368,10 @@ inline napi_addon_register_func GetNapiInitializerCallback(DLib* dlib) {
|
|||||||
reinterpret_cast<napi_addon_register_func>(dlib->GetSymbolAddress(name));
|
reinterpret_cast<napi_addon_register_func>(dlib->GetSymbolAddress(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitModpendingOnce() {
|
||||||
|
CHECK_EQ(0, uv_key_create(&thread_local_modpending));
|
||||||
|
}
|
||||||
|
|
||||||
// DLOpen is process.dlopen(module, filename, flags).
|
// DLOpen is process.dlopen(module, filename, flags).
|
||||||
// Used to load 'module.node' dynamically shared objects.
|
// Used to load 'module.node' dynamically shared objects.
|
||||||
//
|
//
|
||||||
@ -1377,7 +1382,8 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
|
|||||||
Environment* env = Environment::GetCurrent(args);
|
Environment* env = Environment::GetCurrent(args);
|
||||||
auto context = env->context();
|
auto context = env->context();
|
||||||
|
|
||||||
CHECK_NULL(modpending);
|
uv_once(&init_modpending_once, InitModpendingOnce);
|
||||||
|
CHECK_NULL(uv_key_get(&thread_local_modpending));
|
||||||
|
|
||||||
if (args.Length() < 2) {
|
if (args.Length() < 2) {
|
||||||
env->ThrowError("process.dlopen needs at least 2 arguments.");
|
env->ThrowError("process.dlopen needs at least 2 arguments.");
|
||||||
@ -1405,8 +1411,9 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
|
|||||||
// Objects containing v14 or later modules will have registered themselves
|
// Objects containing v14 or later modules will have registered themselves
|
||||||
// on the pending list. Activate all of them now. At present, only one
|
// on the pending list. Activate all of them now. At present, only one
|
||||||
// module per object is supported.
|
// module per object is supported.
|
||||||
node_module* const mp = modpending;
|
node_module* const mp = static_cast<node_module*>(
|
||||||
modpending = nullptr;
|
uv_key_get(&thread_local_modpending));
|
||||||
|
uv_key_set(&thread_local_modpending, nullptr);
|
||||||
|
|
||||||
if (!is_opened) {
|
if (!is_opened) {
|
||||||
Local<String> errmsg = OneByteString(env->isolate(), dlib.errmsg_.c_str());
|
Local<String> errmsg = OneByteString(env->isolate(), dlib.errmsg_.c_str());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user