@@ -117,6 +117,10 @@ typedef int mode_t;
117117#include < grp.h> // getgrnam()
118118#endif
119119
120+ #if defined(__POSIX__)
121+ #include < dlfcn.h>
122+ #endif
123+
120124#ifdef __APPLE__
121125#include < crt_externs.h>
122126#define environ (*_NSGetEnviron ())
@@ -2503,36 +2507,85 @@ struct node_module* get_linked_module(const char* name) {
25032507 return mp;
25042508}
25052509
2506- // DLOpen is process.dlopen(module, filename).
2510+ struct DLib {
2511+ std::string filename_;
2512+ std::string errmsg_;
2513+ void * handle_;
2514+ int flags_;
2515+
2516+ #ifdef __POSIX__
2517+ static const int kDefaultFlags = RTLD_LAZY;
2518+
2519+ bool Open () {
2520+ handle_ = dlopen (filename_.c_str (), flags_);
2521+ if (handle_ != nullptr )
2522+ return true ;
2523+ errmsg_ = dlerror ();
2524+ return false ;
2525+ }
2526+
2527+ void Close () {
2528+ if (handle_ != nullptr )
2529+ dlclose (handle_);
2530+ }
2531+ #else // !__POSIX__
2532+ static const int kDefaultFlags = 0 ;
2533+ uv_lib_t lib_;
2534+
2535+ bool Open () {
2536+ int ret = uv_dlopen (filename_.c_str (), &lib_);
2537+ if (ret == 0 ) {
2538+ handle_ = static_cast <void *>(lib_.handle );
2539+ return true ;
2540+ }
2541+ errmsg_ = uv_dlerror (&lib_);
2542+ uv_dlclose (&lib_);
2543+ return false ;
2544+ }
2545+
2546+ void Close () {
2547+ uv_dlclose (&lib_);
2548+ }
2549+ #endif // !__POSIX__
2550+ };
2551+
2552+ // DLOpen is process.dlopen(module, filename, flags).
25072553// Used to load 'module.node' dynamically shared objects.
25082554//
25092555// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
25102556// when two contexts try to load the same shared object. Maybe have a shadow
25112557// cache that's a plain C list or hash table that's shared across contexts?
25122558static void DLOpen (const FunctionCallbackInfo<Value>& args) {
25132559 Environment* env = Environment::GetCurrent (args);
2514- uv_lib_t lib;
25152560
25162561 CHECK_EQ (modpending, nullptr );
25172562
2518- if (args.Length () != 2 ) {
2519- env->ThrowError (" process.dlopen takes exactly 2 arguments." );
2563+ if (args.Length () < 2 ) {
2564+ env->ThrowError (" process.dlopen needs at least 2 arguments." );
25202565 return ;
25212566 }
25222567
2568+ int32_t flags = DLib::kDefaultFlags ;
2569+ if (args.Length () > 2 && !args[2 ]->Int32Value (env->context ()).To (&flags)) {
2570+ return env->ThrowTypeError (" flag argument must be an integer." );
2571+ }
2572+
25232573 Local<Object> module = args[0 ]->ToObject (env->isolate ()); // Cast
25242574 node::Utf8Value filename (env->isolate (), args[1 ]); // Cast
2525- const bool is_dlopen_error = uv_dlopen (*filename, &lib);
2575+ DLib dlib;
2576+ dlib.filename_ = *filename;
2577+ dlib.flags_ = flags;
2578+ bool is_opened = dlib.Open ();
25262579
25272580 // Objects containing v14 or later modules will have registered themselves
25282581 // on the pending list. Activate all of them now. At present, only one
25292582 // module per object is supported.
25302583 node_module* const mp = modpending;
25312584 modpending = nullptr ;
25322585
2533- if (is_dlopen_error ) {
2534- Local<String> errmsg = OneByteString (env->isolate (), uv_dlerror (&lib ));
2535- uv_dlclose (&lib );
2586+ if (!is_opened ) {
2587+ Local<String> errmsg = OneByteString (env->isolate (), dlib. errmsg_ . c_str ( ));
2588+ dlib. Close ( );
25362589#ifdef _WIN32
25372590 // Windows needs to add the filename into the error message
25382591 errmsg = String::Concat (errmsg, args[1 ]->ToString (env->isolate ()));
@@ -2542,7 +2595,7 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
25422595 }
25432596
25442597 if (mp == nullptr ) {
2545- uv_dlclose (&lib );
2598+ dlib. Close ( );
25462599 env->ThrowError (" Module did not self-register." );
25472600 return ;
25482601 }
@@ -2569,18 +2622,18 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
25692622 }
25702623
25712624 // NOTE: `mp` is allocated inside of the shared library's memory, calling
2572- // `uv_dlclose ` will deallocate it
2573- uv_dlclose (&lib );
2625+ // `dlclose ` will deallocate it
2626+ dlib. Close ( );
25742627 env->ThrowError (errmsg);
25752628 return ;
25762629 }
25772630 if (mp->nm_flags & NM_F_BUILTIN) {
2578- uv_dlclose (&lib );
2631+ dlib. Close ( );
25792632 env->ThrowError (" Built-in module self-registered." );
25802633 return ;
25812634 }
25822635
2583- mp->nm_dso_handle = lib. handle ;
2636+ mp->nm_dso_handle = dlib. handle_ ;
25842637 mp->nm_link = modlist_addon;
25852638 modlist_addon = mp;
25862639
@@ -2592,7 +2645,7 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
25922645 } else if (mp->nm_register_func != nullptr ) {
25932646 mp->nm_register_func (exports, module , mp->nm_priv );
25942647 } else {
2595- uv_dlclose (&lib );
2648+ dlib. Close ( );
25962649 env->ThrowError (" Module has no declared entry point." );
25972650 return ;
25982651 }
0 commit comments