I used ccall
to run a function in a shared library. Now it’s loaded, and I’d like to unload it (say, to change something in the source and rebuild). Libdl.dlcose
looked like it might be what I need, but it takes a handle, and I don’t have one. I tried to get one, but it didn’t help me close the library. Can you unload a library loaded in this way?
x = Libdl.dlopen("name_of_my_library")
Libdl.dlclose(x) # returns false
filter(x->contains(x, "name_of_my_library"), Libdl.dllist()) # Still shows my library as loaded.
On unix-like platforms, dlopen
is reference-counted and the handle is not deleted until the reference count reaches zero. From a quick look, I think jl_dlopen
doesn’t check handle existence before calling the system dlopen
(which will increment and return if the library was already opened in the current process). It’s possible – and likely – that there are multiple calls and a reference count greater than 1 if you are using BinDeps.
For diagnostic purposes, you can also call dlerror
(jl_dlerror
exists internally but is not exported). unsafe_string(ccall(:dlerror, Cstring, ()))
should work.
Thanks @ihnorton. If I understand you correctly, then this is why my method isn’t unloading the library. I think we’re still looking for a way to unload it after a ccall then, yes?
If you were calling
ccall((:my_fcn, "./my_lib.so"), ...)
but needed to close the library when done, then do this instead:
lib = Libdl.dlopen("./my_lib.so")
sym = Libdl.dlsym(lib, :my_fcn)
ccall(sym, ...) # Remaining arguments are the same.
Libdl.dlclose(lib)
More on the GitHub issue: https://github.com/JuliaLang/julia/issues/23459
1 Like