On Tue, Jun 30, 2020 at 13:43:00 +0200, Kamil Rytarowski wrote: > On 30.06.2020 05:16, Jason Thorpe wrote: > > > >> On Jun 29, 2020, at 5:13 PM, Kamil Rytarowski <ka...@netbsd.org> wrote: > >> > >>> <quote> > >>> The atexit() function shall register the function pointed to by func, to > >>> be called without arguments at normal program termination. At normal > >>> program termination, all functions registered by the atexit() function > >>> shall be called, in the reverse order of their registration, except that > >>> a function is called after any previously registered functions that had > >>> already been called at the time it was registered. Normal termination > >>> occurs either by a call to exit() or a return from main(). > >>> </quote> > >>> > >>> My reading of the standard here is that atexit() handlers are called at > >>> "normal program termination", and that "normal program termination" is > >>> explicitly defined as either a call to exit() or returning from main(), > >>> and thus any other call to atexit() handlers is expressly forbidden by > >>> the standard. > >>> > >> > >> There is no word "only", so it's unspecified. > > > > Sorry, but that seems like a huge stretch. Everything seems tied to the > > process "exit" path in the description of atexit(). Even in the > > APPLICATION USAGE section, they have the following informative text: > > > > <quote> > > All functions registered by the atexit() function are called at normal > > process termination, which occurs by a call to the exit() function or a > > return from main() or on the last thread termination, when the behavior is > > as if the implementation called exit() with a zero argument at thread > > termination time. > > </quote> > > > > ...specifically, the "is as if" qualifier. In my reading, if the enclosing > > program is not terminating, then atexit() handlers should not be called. > > > > dlclose() does not initiate "normal program termination" (it's also > > specified in Issue 7, so I double-checked!), nor does it mention anything > > about being considered "normal program termination" from the perspective of > > the shared object that is being closed. > > > > Can you point to another place in the standard that uses the "only" type > > wording to justify your reading of atexit()? > > > > This is an extension and extensions are allowed. > > There is also no better alternative as __cxa_atexit() besides of being > C++ ABI specific, it is documented as internal only: > > "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." > > https://itanium-cxx-abi.github.io/cxx-abi/abi.html > > This is only me, but DSO can be treated as a subprogram loaded after > dlopen() and terminated upon dlclose(). atexit(3) in this metaphor > naturally associates to dlclose().
That's an enticing line of reasoning, and yes one can see how it caused the current atexit abuse (heck, I would have done it myself, people are lazy :), but as all analogies it can only be taken so far. A program termination means the program will be gone very soon, it's memory freed, file descriptors closed, etc. In contrast, the program continues to work after dlclose, so resource leaks are a real concern. So cleanup code that runs at exit time and at the dlclose time have very different operational constraints. atexit-for-dlclose really pushes you further back into MSDOS-like environment where programs are not insulated from each other. -uwe