diff options
author | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2018-12-05 17:24:49 -0800 |
---|---|---|
committer | Gabriel Schulhof <gabriel.schulhof@intel.com> | 2018-12-19 18:35:38 -0800 |
commit | 13abc6adfb9f6a53618ca7d533d31b6a5d26dcec (patch) | |
tree | c926fad94aa23bf3bec5af81b975efa0771338da /src/node_binding.cc | |
parent | 622e348d8f70a4ec006ee1ce9207a6a5bc3fc325 (diff) | |
download | android-node-v8-13abc6adfb9f6a53618ca7d533d31b6a5d26dcec.tar.gz android-node-v8-13abc6adfb9f6a53618ca7d533d31b6a5d26dcec.tar.bz2 android-node-v8-13abc6adfb9f6a53618ca7d533d31b6a5d26dcec.zip |
src: unload addons when environment quits
This is an alternative to https://github.com/nodejs/node/pull/23319
which attaches the loaded addons to the environment and closes them
when the environment is destroyed.
PR-URL: https://github.com/nodejs/node/pull/24861
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'src/node_binding.cc')
-rw-r--r-- | src/node_binding.cc | 182 |
1 files changed, 80 insertions, 102 deletions
diff --git a/src/node_binding.cc b/src/node_binding.cc index 1e78f7c17f..0758741ffc 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -2,10 +2,6 @@ #include "node_internals.h" #include "node_native_module.h" -#if defined(__POSIX__) -#include <dlfcn.h> -#endif - #if HAVE_OPENSSL #define NODE_BUILTIN_OPENSSL_MODULES(V) V(crypto) V(tls_wrap) #else @@ -127,31 +123,8 @@ extern "C" void node_module_register(void* m) { namespace binding { -class DLib { - public: -#ifdef __POSIX__ - static const int kDefaultFlags = RTLD_LAZY; -#else - static const int kDefaultFlags = 0; -#endif - - inline DLib(const char* filename, int flags) - : filename_(filename), flags_(flags), handle_(nullptr) {} - - inline bool Open(); - inline void Close(); - inline void* GetSymbolAddress(const char* name); - - const std::string filename_; - const int flags_; - std::string errmsg_; - void* handle_; -#ifndef __POSIX__ - uv_lib_t lib_; -#endif - private: - DISALLOW_COPY_AND_ASSIGN(DLib); -}; +DLib::DLib(const char* filename, int flags) + : filename_(filename), flags_(flags), handle_(nullptr) {} #ifdef __POSIX__ bool DLib::Open() { @@ -248,87 +221,92 @@ 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 = - static_cast<node_module*>(uv_key_get(&thread_local_modpending)); - uv_key_set(&thread_local_modpending, nullptr); - - if (!is_opened) { - Local<String> errmsg = OneByteString(env->isolate(), dlib.errmsg_.c_str()); - dlib.Close(); + env->TryLoadAddon(*filename, flags, [&](DLib* dlib) { + const 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 = + static_cast<node_module*>(uv_key_get(&thread_local_modpending)); + uv_key_set(&thread_local_modpending, nullptr); + + if (!is_opened) { + Local<String> errmsg = + OneByteString(env->isolate(), dlib->errmsg_.c_str()); + dlib->Close(); #ifdef _WIN32 - // Windows needs to add the filename into the error message - errmsg = String::Concat( - env->isolate(), errmsg, args[1]->ToString(context).ToLocalChecked()); + // Windows needs to add the filename into the error message + errmsg = String::Concat( + env->isolate(), errmsg, args[1]->ToString(context).ToLocalChecked()); #endif // _WIN32 - env->isolate()->ThrowException(Exception::Error(errmsg)); - return; - } + env->isolate()->ThrowException(Exception::Error(errmsg)); + return false; + } - if (mp == nullptr) { - if (auto callback = GetInitializerCallback(&dlib)) { - callback(exports, module, context); - } else if (auto napi_callback = GetNapiInitializerCallback(&dlib)) { - napi_module_register_by_symbol(exports, module, context, napi_callback); - } else { - dlib.Close(); - env->ThrowError("Module did not self-register."); + if (mp == nullptr) { + if (auto callback = GetInitializerCallback(dlib)) { + callback(exports, module, context); + } else if (auto napi_callback = GetNapiInitializerCallback(dlib)) { + napi_module_register_by_symbol(exports, module, context, napi_callback); + } else { + dlib->Close(); + env->ThrowError("Module did not self-register."); + return false; + } + return true; } - return; - } - // -1 is used for N-API modules - if ((mp->nm_version != -1) && (mp->nm_version != NODE_MODULE_VERSION)) { - // Even if the module did self-register, it may have done so with the wrong - // version. We must only give up after having checked to see if it has an - // appropriate initializer callback. - if (auto callback = GetInitializerCallback(&dlib)) { - callback(exports, module, context); - return; + // -1 is used for N-API modules + if ((mp->nm_version != -1) && (mp->nm_version != NODE_MODULE_VERSION)) { + // Even if the module did self-register, it may have done so with the + // wrong version. We must only give up after having checked to see if it + // has an appropriate initializer callback. + if (auto callback = GetInitializerCallback(dlib)) { + callback(exports, module, context); + return true; + } + char errmsg[1024]; + snprintf(errmsg, + sizeof(errmsg), + "The module '%s'" + "\nwas compiled against a different Node.js version using" + "\nNODE_MODULE_VERSION %d. This version of Node.js requires" + "\nNODE_MODULE_VERSION %d. Please try re-compiling or " + "re-installing\nthe module (for instance, using `npm rebuild` " + "or `npm install`).", + *filename, + mp->nm_version, + NODE_MODULE_VERSION); + + // NOTE: `mp` is allocated inside of the shared library's memory, calling + // `dlclose` will deallocate it + dlib->Close(); + env->ThrowError(errmsg); + return false; + } + if (mp->nm_flags & NM_F_BUILTIN) { + dlib->Close(); + env->ThrowError("Built-in module self-registered."); + return false; } - char errmsg[1024]; - snprintf(errmsg, - sizeof(errmsg), - "The module '%s'" - "\nwas compiled against a different Node.js version using" - "\nNODE_MODULE_VERSION %d. This version of Node.js requires" - "\nNODE_MODULE_VERSION %d. Please try re-compiling or " - "re-installing\nthe module (for instance, using `npm rebuild` " - "or `npm install`).", - *filename, - mp->nm_version, - NODE_MODULE_VERSION); - - // NOTE: `mp` is allocated inside of the shared library's memory, calling - // `dlclose` will deallocate it - dlib.Close(); - env->ThrowError(errmsg); - return; - } - if (mp->nm_flags & NM_F_BUILTIN) { - dlib.Close(); - env->ThrowError("Built-in module self-registered."); - return; - } - mp->nm_dso_handle = dlib.handle_; - mp->nm_link = modlist_addon; - modlist_addon = mp; + mp->nm_dso_handle = dlib->handle_; + mp->nm_link = modlist_addon; + modlist_addon = mp; - if (mp->nm_context_register_func != nullptr) { - mp->nm_context_register_func(exports, module, context, mp->nm_priv); - } else if (mp->nm_register_func != nullptr) { - mp->nm_register_func(exports, module, mp->nm_priv); - } else { - dlib.Close(); - env->ThrowError("Module has no declared entry point."); - return; - } + if (mp->nm_context_register_func != nullptr) { + mp->nm_context_register_func(exports, module, context, mp->nm_priv); + } else if (mp->nm_register_func != nullptr) { + mp->nm_register_func(exports, module, mp->nm_priv); + } else { + dlib->Close(); + env->ThrowError("Module has no declared entry point."); + return false; + } + + return true; + }); // Tell coverity that 'handle' should not be freed when we return. // coverity[leaked_storage] |