Skip to content

Commit

Permalink
src: fix addon loader regression
Browse files Browse the repository at this point in the history
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: nodejs#154
Reviewed-By: Ryan Graham <[email protected]>
  • Loading branch information
bnoordhuis committed Dec 13, 2014
1 parent 370e821 commit a60056d
Showing 1 changed file with 12 additions and 15 deletions.
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

0 comments on commit a60056d

Please sign in to comment.