Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
src: fix addon loader regression
Fix a regression that was introduced in commit a38b917 by removing the
bad check.  Also rearrange the addon loading logic to ensure that the
list of pending addons remains in a consistent state when the shared
object fails to load; in particular, when an addon self-registers first,
then hits a dynamic linker error in a later constructor.

Fixes the following asserting when loading a .node shared object:

    node: ../src/node.cc:1944: void node::node_module_register(void*):
    Assertion `(modpending) != (nullptr)' failed.

Fixes strongloop/strongops#233.

PR-URL: #154
Reviewed-By: Ryan Graham <ryan@strongloop.com>
  • Loading branch information
bnoordhuis committed Dec 13, 2014
commit a60056df3cad2867d337fc1d7adeebe66f89031a
27 changes: 12 additions & 15 deletions src/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1939,9 +1939,6 @@ extern "C" void node_module_register(void* m) {
mp->nm_link = modlist_linked;
modlist_linked = mp;
} else {
// Once node::Init was called we can only register dynamic modules.
// See DLOpen.
CHECK_NE(modpending, nullptr);
modpending = mp;
}
}
Expand Down Expand Up @@ -1980,21 +1977,26 @@ typedef void (UV_DYNAMIC* extInit)(Handle<Object> exports);
// cache that's a plain C list or hash table that's shared across contexts?
void DLOpen(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
struct node_module* mp;
uv_lib_t lib;

CHECK_EQ(modpending, nullptr);

if (args.Length() < 2) {
env->ThrowError("process.dlopen takes exactly 2 arguments.");
return;
}

Local<Object> module = args[0]->ToObject(); // Cast
node::Utf8Value filename(args[1]); // Cast
const bool is_dlopen_error = uv_dlopen(*filename, &lib);

Local<String> exports_string = env->exports_string();
Local<Object> exports = module->Get(exports_string)->ToObject();
// 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;

if (uv_dlopen(*filename, &lib)) {
if (is_dlopen_error) {
Local<String> errmsg = OneByteString(env->isolate(), uv_dlerror(&lib));
#ifdef _WIN32
// Windows needs to add the filename into the error message
Expand All @@ -2004,14 +2006,6 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
return;
}

/*
* 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.
*/
mp = modpending;
modpending = nullptr;

if (mp == nullptr) {
env->ThrowError("Module did not self-register.");
return;
Expand All @@ -2034,6 +2028,9 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
mp->nm_link = modlist_addon;
modlist_addon = mp;

Local<String> exports_string = env->exports_string();
Local<Object> exports = module->Get(exports_string)->ToObject();

if (mp->nm_context_register_func != nullptr) {
mp->nm_context_register_func(exports, module, env->context(), mp->nm_priv);
} else if (mp->nm_register_func != nullptr) {
Expand Down