Skip to content

Commit 78159c3

Browse files
committed
src: permit native modules to be loaded in more than one context
Maintain metadata on loaded native modules so that if additional contexts load the same module, the metadata will be reused and the registration function dispatched again. Fix race condition where if multiple contexts load modules at the same time, it's possible one of them could fail to load.
1 parent 537a4ba commit 78159c3

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

src/node.cc

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,9 @@ static int v8_thread_pool_size = v8_default_thread_pool_size;
183183
static bool prof_process = false;
184184
static bool v8_is_profiling = false;
185185
static bool node_is_initialized = false;
186+
static Mutex module_mutex;
186187
static node_module* modpending;
188+
static std::unordered_map<std::string, node_module *> modmap_metadata;
187189
static node_module* modlist_builtin;
188190
static node_module* modlist_internal;
189191
static node_module* modlist_linked;
@@ -1266,8 +1268,6 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
12661268
Environment* env = Environment::GetCurrent(args);
12671269
auto context = env->context();
12681270

1269-
CHECK_NULL(modpending);
1270-
12711271
if (args.Length() < 2) {
12721272
env->ThrowError("process.dlopen needs at least 2 arguments.");
12731273
return;
@@ -1289,13 +1289,27 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
12891289

12901290
node::Utf8Value filename(env->isolate(), args[1]); // Cast
12911291
DLib dlib(*filename, flags);
1292-
bool is_opened = dlib.Open();
1293-
1294-
// Objects containing v14 or later modules will have registered themselves
1295-
// on the pending list. Activate all of them now. At present, only one
1296-
// module per object is supported.
1297-
node_module* const mp = modpending;
1298-
modpending = nullptr;
1292+
bool is_opened;
1293+
node_module* mp;
1294+
{
1295+
Mutex::ScopedLock lock(module_mutex);
1296+
CHECK_NULL(modpending);
1297+
is_opened = dlib.Open();
1298+
// Objects containing v14 or later modules will have registered themselves
1299+
// on the pending list. Activate all of them now. At present, only one
1300+
// module per object is supported.
1301+
std::string key(*filename, filename.length());
1302+
mp = modpending;
1303+
if (mp) {
1304+
modpending = nullptr;
1305+
modmap_metadata.emplace(std::move(key), mp);
1306+
} else {
1307+
auto existing = modmap_metadata.find(key);
1308+
if (existing != modmap_metadata.end()) {
1309+
mp = existing->second;
1310+
}
1311+
}
1312+
}
12991313

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

0 commit comments

Comments
 (0)