Red Hat Bugzilla – Bug 28625
dlopen + atexit + dlclose = SIGSEGV segmentation fault
Last modified: 2016-11-24 10:02:52 EST
If a dlopen-ed shared module registers an atexit function and is then
dlclose-d, the main() function will crash after its return, because the
function is no longer in memory when it gets called.
IMNSHO Whilst a blinkered view of atexit functionality will say "Yes,
that's correct", it goes against the intent of using dlopen & dlclose to
DYNAMICALLY load and unload modules; dlclose should perform the functions
from atexit calls made within the loaded module.
$rpm -qa | grep libc
Linux ws2.rsctech.net 2.2.16-22smp #1 SMP Tue Aug 22 16:39:21 EDT 2000
This has been registered as libc/2092 with gnu.org, but nothing seems to
have happened with it there - it might have gone to dev/null because they
expect all libc bugs to be reported here.
I have a tar file with self-contained example of this (Is there an option
to attach this somewhere?)
Created attachment 10640 [details]
tar of 3 .cpp files & a script_both to demonstrate problem
atexit semantics cannot be changed.
Have a look at __cxa_atexit and __cxa_finalize functions though, they are
exactly what you're looking on.
g++ even uses them instead of atexit if you pass it -fuse-cxa-atexit option.
Your answer may be technically correct, but is tantalisingly useless, because:
- "info glibc" has no reference to __cxa_atexit.
- in /usr/include, "grep -r _atexit *" just finds g_atexit.
- "info g++", "man g++" have no reference to -fuse-cxa-atexit option,
- "g++ -v --help" mentions it to use __cxa_atexit to register destructors; this
is not quite what I had in mind.
- I do not wish to code an atexit in a dlopen-ed module, but I have ported
applications that crash because atexit is are compiled into modules like
libdb2.so - ready-made and no source to hand. I have tried to use "ld --wrap
atexit"; ironically, this works for non-dynamic loading (when it isn't needed),
but is ignored for dlopen-ed modules (when it's needed).
Also, your "atexit semantics cannot be changed" is misleading, and indicates a
lack of understanding on how standards evolve.
To summarise, I am unable to use ANY of the information you have given to me.
I'm sorry that I am so ignorant about Linux, but I need to know how I may turn
your statements into something useful, as the avenues I usually use fail to
corroborate your comments. Indeed, it appears to me that someone has chosen a
rather inelegant solution to an obvious problem, and hidden it away.
Is there someone else more experienced that I could get in touch with? Although
somewhat inexperienced with Linux, I have a wealth of experience writing
compilers, run-time linkers and operating systems drivers, as well as the more
mundane applications stuff.
Note that my email address is about to change to email@example.com (from
XYZZY? PLUGH? What magic word must I utter, what hurdles must I jump in order
to make contact with someone who knows what they're talking about? This is very
Having looked at the __cxa_atexit interface, I have some ideas that may (or may
not!) be feasible to resolve the atexit/DSO issue, that I could discuss with
someone who understands loader routines.
Incidentally, Ulrich Drepper has contacted me re gnats libc/2092, but his
comments also show me that he too has failed to grasp the differences between a
compiler, linker and loader, and so what libc is about. I've also discovered
that he is responsible for maintaining libc!
I have found further information which confirms to me that the earlier answer
you gave was wrong; I'll quote two of them here:
There is an interesting comment at
http://reality.sgi.com/dehnert_engr/cxx/abi.html (C++ ABI for IA-64 (Draft)
Revised 17 November 2000), section 184.108.40.206-B, last sentence: "No user interface
to __cxa_atexit is supported, so the user is not able to register an atexit
function with a parameter or a home DSO."
Also, at http://www.gnu.org/software/libc/FAQ.html , 3.12 states "ISO C states
that identifiers beginning with an underscore are internal to the libc. An
application program normally shouldn't use those internal interfaces (there are
exceptions, e.g. __ivaliduser). If a program uses these interfaces, it's
broken. These internal interfaces might change between glibc releases or
Is __cxa_atexit an exception also?
Ulrich Drepper actually changed atexit semantics and it is pending review
by the standard comittees. The next atexit is present in glibc-2.2.2-7 in rawhide.