@@ -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