Skip to content

Commit

Permalink
src: permit native modules to be loaded in more than one context
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rpetrich committed Jun 25, 2018
1 parent 537a4ba commit 78159c3
Showing 1 changed file with 23 additions and 9 deletions.
32 changes: 23 additions & 9 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ static int v8_thread_pool_size = v8_default_thread_pool_size;
static bool prof_process = false;
static bool v8_is_profiling = false;
static bool node_is_initialized = false;
static Mutex module_mutex;
static node_module* modpending;
static std::unordered_map<std::string, node_module *> modmap_metadata;
static node_module* modlist_builtin;
static node_module* modlist_internal;
static node_module* modlist_linked;
Expand Down Expand Up @@ -1266,8 +1268,6 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
auto context = env->context();

CHECK_NULL(modpending);

if (args.Length() < 2) {
env->ThrowError("process.dlopen needs at least 2 arguments.");
return;
Expand All @@ -1289,13 +1289,27 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {

node::Utf8Value filename(env->isolate(), args[1]); // Cast
DLib dlib(*filename, flags);
bool is_opened = dlib.Open();

// Objects containing v14 or later modules will have registered themselves
// on the pending list. Activate all of them now. At present, only one
// module per object is supported.
node_module* const mp = modpending;
modpending = nullptr;
bool is_opened;
node_module* mp;
{
Mutex::ScopedLock lock(module_mutex);
CHECK_NULL(modpending);
is_opened = dlib.Open();
// Objects containing v14 or later modules will have registered themselves
// on the pending list. Activate all of them now. At present, only one
// module per object is supported.
std::string key(*filename, filename.length());
mp = modpending;
if (mp) {
modpending = nullptr;
modmap_metadata.emplace(std::move(key), mp);
} else {
auto existing = modmap_metadata.find(key);
if (existing != modmap_metadata.end()) {
mp = existing->second;
}
}
}

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

0 comments on commit 78159c3

Please sign in to comment.