aboutsummaryrefslogtreecommitdiff
path: root/src/node_binding.cc
diff options
context:
space:
mode:
authorGabriel Schulhof <gabriel.schulhof@intel.com>2018-12-05 17:24:49 -0800
committerGabriel Schulhof <gabriel.schulhof@intel.com>2018-12-19 18:35:38 -0800
commit13abc6adfb9f6a53618ca7d533d31b6a5d26dcec (patch)
treec926fad94aa23bf3bec5af81b975efa0771338da /src/node_binding.cc
parent622e348d8f70a4ec006ee1ce9207a6a5bc3fc325 (diff)
downloadandroid-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.cc182
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]