Passing null to dlclose()
If it is not documented, it is most likely not (or at "best" undefined).
Actually a simple test could verify that for your platform:
Compiling this
#include <dlfcn.h>
int main()
{
dlclose(0);
}
Already yields the following compiler warning (gcc):
test.c: In function ‘main’:
test.c:5:2: warning: null argument where non-null required (argument 1) [-Wnonnull]
5 | dlclose(0);
| ^~~~~~~
/usr/bin/ld: /tmp/ccYF9oqz.o: in function `main':
An running it, crashes as expected with a segmentation fault.
Why you want to do or need to know this in the first place is the question.
It should be trivial to do a null-check before calling dlclose
or provide
a wrapper that does it, if otherwise inconvenient.
Situation of handle after dlclose()/FreeLibrary() fails
Once you call dlcose the handle is no longer valid for your use:
http://pubs.opengroup.org/onlinepubs/007904975/functions/dlclose.html
Once an object has been closed using dlclose() an application should assume that its symbols are no longer available to dlsym().
It is quite possible that dlclose()
does nothing. Because other libraries also have handles to the library. If the close fails then it usually means somebody else is using it. BUT that does not mean you can use it again via your handle (that is dead).
An error usually indicates your handle is invalid.
How to safely update a running dynamic library?
The dlclose()
which you mark as possibly unsafe is, in fact, definitely unsafe. Any functions from the module currently active in other threads will have the floor pulled out from underneath them: their references to static data and other functions in the module will become dangling pointers.
So I'd say that you're better working out how to have two active versions of your module. You can't do that by just calling dlopen
with the same path, because it caches open handles and it will just return the currently open handle with an incremented reference count. Instead, you can probably do the following:
Compile your modules into files with an included version number, and then symlink the official module filename to the latest version. (That's the way most
.so
files are generated on a typical Unix system.)When you want to open a module, first use
readlink(2)
to find the currently-linked module version. Then open that path.
(I haven't actually tried that but I think it will work, at least on Unix-like systems.)
I'd suggest trying to avoid RTLD_GLOBAL
, if possible. In general, dlclose
ing a module opened with RTLD_GLOBAL
is risky, at least; the dlclose
might orphan resolved symbols used by other dynamically loaded modules. (And if no other module is going to use the symbols exported by the module you might dlclose
, then RTLD_GLOBAL
was never necessary.) I'm not convinced that RTLD_LAZY
is a good idea, either.
Finally, you'll have to come up with some way to know when it is possible to dlclose
old modules. You can't do it until you are certain that no thread is currently calling a function from the obsolete module. You might want to consider putting a reference count into the module structure, and using a macro or wrapper to ensure that reference counts are incremented and decremented pre- and post-call. You'll also want to add some kind of mutex to the module structure in order to avoid race conditions.
dlsym returns NULL, even though the symbol exists
I don't think you can do that, dlsym
works on exported symbols. Because you're doing dlsym
on NULL
(current image), even though the symbols are present in the executable ELF image, they're not exported (since it's not a shared library).
Why not call it directly and let the linker take care of it? There's no point in using dlsym
to get symbols from the same image as your dlsym
call. If your testing
symbol was in a shared library that you either linked against or loaded using dlopen
then you would be able to retrieve it.
I believe there's also a way of exporting symbols when building executables (-Wl,--export-dynamic
as mentioned in a comment by Brandon) but I'm not sure why you'd want to do that.
Related Topics
Find Command Find Directories That Were Created After a Certain Date Under Linux/Cygwin
How to Set the Socket Option So_Reuseport in Rust
Curl Command Doesn't Work in Bash Script
Serialport in Mono in Linux Not Responding to Datareceived Event
Using Sed to Print Between Two Patterns
Bash: Checking If Files Are Duplicates Within a Directory
Permission Denied (Publickey), on Linux Aws Server How to Fix It
How to Detect a Blank Column in a Page Using Imagemagick to Distinguish Two Column Papers
How to Install Python Package Installer Pip on Ubuntu 20.04 Linux
Re-Encoding Only Images of a PDF? (Or, Ghostscript Fails on 8-Bit Rgb While Optimizing)
Script Produces Different Result When Executed by Bash Than by Cron
Why Can't Cuda's Examples Makefile Find the Cuda Libraries
Is Ethernet Checksum Exposed via Af_Packet
How to Display Filename from a Column Using Awk
How to Split Flv File by Size Using Ffmpeg or Mencoder or Smth Else