On Sat, 20 Dec 2025 15:50:34 +0100
Martin Husemann <[email protected]> wrote:

> On Sat, Dec 20, 2025 at 02:16:34PM +0000, Sad Clouds wrote:
> > As far as I understand the standard does not specify this behavior. I'm
> > not saying there is no value in "fixing" it, but then this would not be
> > strictly compliant with the standard, right?
> > https://pubs.opengroup.org/onlinepubs/9799919799/functions/atexit.html
> 
> The problem is that neither Posix nor the C standard define a way to
> unregister an atexit() registered function, which you would have to
> do on dlclose() of the DSO that defines the function. And if there
> would be something like unatexit(3), you would need a destructor
> function to invoke it at dlclose() time.
> 
> The whole atexit(3) interface makes no sense in the context of manual
> dlopen()/dlclose() during runtime. Destructor semantics are much better
> and clearer for this case.
> 
> Martin

I haven't looked at the implementation but I imagine on Linux when
dlclose() is called, all of the atexit() handlers are scanned and
checked to see if they point to the address space of the shared object
that is being closed. If any of them match, they are executed and then
removed from the list, so they are not called again on exit(). This way
the clean up handlers can be regular functions and don't need to be
marked as destructors.

None of this is specified by the standard and is essentially a hack to
work around buggy code misusing atexit(). For isolated cases where it
causes issue, instead of hacking NetBSD libc it is probably safer to
simply fix the issue at source, i.e. open a bug upstream on X11.

I've never seen anyone using atexit() with shared libraries. The usual
mechanisms for these things are _init/_fini or
__attribute__((constructor))/__attribute__((destructor)).

Reply via email to