This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 5a88ac388 fix(rust/driver_manager): don't dlclose drivers (#3844)
5a88ac388 is described below

commit 5a88ac3880e739373682a1663df07bfc67edf2aa
Author: Pranav Joglekar <[email protected]>
AuthorDate: Tue Jan 6 05:35:09 2026 +0530

    fix(rust/driver_manager): don't dlclose drivers (#3844)
    
    According to
    https://github.com/golang/go/issues/11100#issuecomment-932638093,
    `-Wl,-z,nodelete` does not work on macos. This causes dlclose to be
    called when the shared library is dropped, which results in unexpected
    behaviour (I've observed the program hangs because Go cannot kill the
    goroutines and so waits for them to close)
    
    This PR fixes the problem by ensuring that we explicitly open the
    library with `RTLD_NODELETE` flag which ensures that `dlclose` is not
    called during unload.
    
    
    Fixes #3840.
---
 rust/driver_manager/Cargo.toml |  2 +-
 rust/driver_manager/src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/rust/driver_manager/Cargo.toml b/rust/driver_manager/Cargo.toml
index fa98952e5..f3d18c84c 100644
--- a/rust/driver_manager/Cargo.toml
+++ b/rust/driver_manager/Cargo.toml
@@ -39,7 +39,7 @@ adbc_core.workspace = true
 adbc_ffi.workspace = true
 arrow-array.workspace = true
 arrow-schema.workspace = true
-libloading = "0.8"
+libloading = "0.8.8"
 toml = { version = "0.9.10", default-features = false, features = [
     "parse",
     "display",
diff --git a/rust/driver_manager/src/lib.rs b/rust/driver_manager/src/lib.rs
index 173b60d06..8ecf38829 100644
--- a/rust/driver_manager/src/lib.rs
+++ b/rust/driver_manager/src/lib.rs
@@ -381,8 +381,59 @@ impl ManagedDriver {
         let default_entrypoint = get_default_entrypoint(filename.as_ref());
 
         let entrypoint = entrypoint.unwrap_or(default_entrypoint.as_bytes());
-        let library = unsafe {
-            
libloading::Library::new(filename.as_ref()).map_err(libloading_error_to_adbc_error)?
+        // By default, go builds the libraries with '-Wl -z nodelete' which 
does not
+        // unload the go runtime. This isn't respected on mac ( 
https://github.com/golang/go/issues/11100#issuecomment-932638093 )
+        // so we need to explicitly load the library with RTLD_NODELETE( which 
prevents unloading )
+        #[cfg(unix)]
+        let library: libloading::Library = unsafe {
+            use std::os::raw::c_int;
+
+            const RTLD_NODELETE: c_int = if cfg!(any(
+                target_os = "macos",
+                target_os = "ios",
+                target_os = "tvos",
+                target_os = "visionos",
+                target_os = "watchos",
+            )) {
+                0x80
+            } else if cfg!(any(
+                target_os = "linux",
+                target_os = "android",
+                target_os = "emscripten",
+                target_os = "freebsd",
+                target_os = "dragonfly",
+                target_os = "openbsd",
+                target_os = "haiku",
+                target_os = "solaris",
+                target_os = "illumos",
+                target_env = "uclibc",
+                target_env = "newlib",
+                target_os = "fuchsia",
+                target_os = "redox",
+                target_os = "hurd",
+                target_os = "cygwin",
+            )) {
+                0x1000
+            } else {
+                0x0
+            };
+
+            libloading::os::unix::Library::open(
+                Some(filename.as_ref()),
+                libloading::os::unix::RTLD_LAZY | 
libloading::os::unix::RTLD_LOCAL | RTLD_NODELETE,
+            )
+            .map(Into::into)
+            .map_err(libloading_error_to_adbc_error)?
+        };
+        // on windows, we emulate the same behaviour by using the 
GET_MODULE_HANDLE_EX_FLAG_PIN. The `.pin()`
+        // function implements this.
+        #[cfg(windows)]
+        let library: libloading::Library = unsafe {
+            let library: libloading::os::windows::Library =
+                libloading::os::windows::Library::new(filename.as_ref())
+                    .map_err(libloading_error_to_adbc_error)?;
+            library.pin().map_err(libloading_error_to_adbc_error)?;
+            library.into()
         };
         let init: libloading::Symbol<adbc_ffi::FFI_AdbcDriverInitFunc> = 
unsafe {
             library

Reply via email to