@@ -103,7 +103,6 @@ using v8::Value;
103103// Globals per process
104104static node_module* modlist_internal;
105105static node_module* modlist_linked;
106- static node_module* modlist_addon;
107106static uv_once_t init_modpending_once = UV_ONCE_INIT;
108107static uv_key_t thread_local_modpending;
109108
@@ -129,6 +128,48 @@ extern "C" void node_module_register(void* m) {
129128
130129namespace binding {
131130
131+ static struct global_handle_map_t {
132+ public:
133+ void set (void * handle, node_module* mod) {
134+ CHECK_NE (handle, nullptr );
135+ Mutex::ScopedLock lock (mutex_);
136+
137+ map_[handle] = Entry { 1 , mod };
138+ }
139+
140+ node_module* get_and_increase_refcount (void * handle) {
141+ CHECK_NE (handle, nullptr );
142+ Mutex::ScopedLock lock (mutex_);
143+
144+ auto it = map_.find (handle);
145+ if (it == map_.end ()) return nullptr ;
146+ it->second .refcount ++;
147+ return it->second .module ;
148+ }
149+
150+ void erase (void * handle) {
151+ CHECK_NE (handle, nullptr );
152+ Mutex::ScopedLock lock (mutex_);
153+
154+ auto it = map_.find (handle);
155+ if (it == map_.end ()) return ;
156+ CHECK_GE (it->second .refcount , 1 );
157+ if (--it->second .refcount == 0 ) {
158+ if (it->second .module ->nm_flags & NM_F_DELETEME)
159+ delete it->second .module ;
160+ map_.erase (handle);
161+ }
162+ }
163+
164+ private:
165+ Mutex mutex_;
166+ struct Entry {
167+ unsigned int refcount;
168+ node_module* module ;
169+ };
170+ std::unordered_map<void *, Entry> map_;
171+ } global_handle_map;
172+
132173DLib::DLib (const char * filename, int flags)
133174 : filename_(filename), flags_(flags), handle_(nullptr ) {}
134175
@@ -142,6 +183,7 @@ bool DLib::Open() {
142183
143184void DLib::Close () {
144185 if (handle_ == nullptr ) return ;
186+ global_handle_map.erase (handle_);
145187 dlclose (handle_);
146188 handle_ = nullptr ;
147189}
@@ -233,7 +275,7 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
233275 // Objects containing v14 or later modules will have registered themselves
234276 // on the pending list. Activate all of them now. At present, only one
235277 // module per object is supported.
236- node_module* const mp =
278+ node_module* mp =
237279 static_cast <node_module*>(uv_key_get (&thread_local_modpending));
238280 uv_key_set (&thread_local_modpending, nullptr );
239281
@@ -250,17 +292,24 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
250292 return false ;
251293 }
252294
253- if (mp == nullptr ) {
295+ if (mp != nullptr ) {
296+ mp->nm_dso_handle = dlib->handle_ ;
297+ global_handle_map.set (dlib->handle_ , mp);
298+ } else {
254299 if (auto callback = GetInitializerCallback (dlib)) {
255300 callback (exports, module , context);
301+ return true ;
256302 } else if (auto napi_callback = GetNapiInitializerCallback (dlib)) {
257303 napi_module_register_by_symbol (exports, module , context, napi_callback);
304+ return true ;
258305 } else {
259- dlib->Close ();
260- env->ThrowError (" Module did not self-register." );
261- return false ;
306+ mp = global_handle_map.get_and_increase_refcount (dlib->handle_ );
307+ if (mp == nullptr || mp->nm_context_register_func == nullptr ) {
308+ dlib->Close ();
309+ env->ThrowError (" Module did not self-register." );
310+ return false ;
311+ }
262312 }
263- return true ;
264313 }
265314
266315 // -1 is used for N-API modules
@@ -293,10 +342,6 @@ void DLOpen(const FunctionCallbackInfo<Value>& args) {
293342 }
294343 CHECK_EQ (mp->nm_flags & NM_F_BUILTIN, 0 );
295344
296- mp->nm_dso_handle = dlib->handle_ ;
297- mp->nm_link = modlist_addon;
298- modlist_addon = mp;
299-
300345 if (mp->nm_context_register_func != nullptr ) {
301346 mp->nm_context_register_func (exports, module , context, mp->nm_priv );
302347 } else if (mp->nm_register_func != nullptr ) {
0 commit comments