From 2a474aa50decad4fcd8980652ab7f6bab1a0a85d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Wed, 20 Feb 2019 15:58:25 +0100 Subject: [PATCH] fixup! worker: improve integration with native addons --- src/node_binding.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/node_binding.cc b/src/node_binding.cc index 68cc0fc42a653d..be098b58093645 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -173,6 +173,7 @@ int wrapped_dlclose(void* handle) { Mutex::ScopedLock lock(dlhandles_mutex); dl_wrap* wrap = static_cast(handle); int ret = 0; + CHECK_GE(wrap->refcount, 1); if (--wrap->refcount == 0) { ret = dlclose(wrap->real_handle); if (ret != 0) dlerror_storage = dlerror(); @@ -183,6 +184,8 @@ int wrapped_dlclose(void* handle) { } void* wrapped_dlsym(void* handle, const char* symbol) { + if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) + return dlsym(handle, symbol); dl_wrap* wrap = static_cast(handle); return dlsym(wrap->real_handle, symbol); } @@ -292,9 +295,17 @@ bool DLib::Open() { void DLib::Close() { if (handle_ == nullptr) return; - if (has_entry_in_global_handle_map_) - global_handle_map.erase(handle_); - dlclose(handle_); + int err = dlclose(handle_); + + if (err == 0) { + // musl libc implements dlclose() as a no-op which returns 1. + // As a consequence, trying to re-load a previously closed addon at a later + // point will not call its static constructors, which Node.js uses. + // Therefore, when dlclose() fails, we assume that the shared object + // still exists and keep it in our handle map. + if (has_entry_in_global_handle_map_) + global_handle_map.erase(handle_); + } handle_ = nullptr; }