@@ -117,6 +117,10 @@ typedef int mode_t;
117
117
#include < grp.h> // getgrnam()
118
118
#endif
119
119
120
+ #if defined(__POSIX__)
121
+ #include < dlfcn.h>
122
+ #endif
123
+
120
124
#ifdef __APPLE__
121
125
#include < crt_externs.h>
122
126
#define environ (*_NSGetEnviron ())
@@ -2503,36 +2507,85 @@ struct node_module* get_linked_module(const char* name) {
2503
2507
return mp;
2504
2508
}
2505
2509
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).
2507
2553
// Used to load 'module.node' dynamically shared objects.
2508
2554
//
2509
2555
// FIXME(bnoordhuis) Not multi-context ready. TBD how to resolve the conflict
2510
2556
// when two contexts try to load the same shared object. Maybe have a shadow
2511
2557
// cache that's a plain C list or hash table that's shared across contexts?
2512
2558
static void DLOpen (const FunctionCallbackInfo<Value>& args) {
2513
2559
Environment* env = Environment::GetCurrent (args);
2514
- uv_lib_t lib;
2515
2560
2516
2561
CHECK_EQ (modpending, nullptr );
2517
2562
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." );
2520
2565
return ;
2521
2566
}
2522
2567
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
+
2523
2573
Local<Object> module = args[0 ]->ToObject (env->isolate ()); // Cast
2524
2574
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 ();
2526
2579
2527
2580
// Objects containing v14 or later modules will have registered themselves
2528
2581
// on the pending list. Activate all of them now. At present, only one
2529
2582
// module per object is supported.
2530
2583
node_module* const mp = modpending;
2531
2584
modpending = nullptr ;
2532
2585
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 ( );
2536
2589
#ifdef _WIN32
2537
2590
// Windows needs to add the filename into the error message
2538
2591
errmsg = String::Concat (errmsg, args[1 ]->ToString (env->isolate ()));
@@ -2542,7 +2595,7 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
2542
2595
}
2543
2596
2544
2597
if (mp == nullptr ) {
2545
- uv_dlclose (&lib );
2598
+ dlib. Close ( );
2546
2599
env->ThrowError (" Module did not self-register." );
2547
2600
return ;
2548
2601
}
@@ -2569,18 +2622,18 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
2569
2622
}
2570
2623
2571
2624
// 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 ( );
2574
2627
env->ThrowError (errmsg);
2575
2628
return ;
2576
2629
}
2577
2630
if (mp->nm_flags & NM_F_BUILTIN) {
2578
- uv_dlclose (&lib );
2631
+ dlib. Close ( );
2579
2632
env->ThrowError (" Built-in module self-registered." );
2580
2633
return ;
2581
2634
}
2582
2635
2583
- mp->nm_dso_handle = lib. handle ;
2636
+ mp->nm_dso_handle = dlib. handle_ ;
2584
2637
mp->nm_link = modlist_addon;
2585
2638
modlist_addon = mp;
2586
2639
@@ -2592,7 +2645,7 @@ static void DLOpen(const FunctionCallbackInfo<Value>& args) {
2592
2645
} else if (mp->nm_register_func != nullptr ) {
2593
2646
mp->nm_register_func (exports, module, mp->nm_priv );
2594
2647
} else {
2595
- uv_dlclose (&lib );
2648
+ dlib. Close ( );
2596
2649
env->ThrowError (" Module has no declared entry point." );
2597
2650
return ;
2598
2651
}
0 commit comments