On 30.06.2020 15:49, Valery Ushakov wrote:
> On Tue, Jun 30, 2020 at 15:09:14 +0200, Kamil Rytarowski wrote:
> 
>> On 30.06.2020 14:24, Valery Ushakov wrote:
>>> 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.
>>
>> Dynamic loading and unloading code predates MSDOS. It also predates
>> shared libraries in UNIX (e.g. Lisp C bindings, predating MSDOS).
> 
> What are you even talking about?!  You go out of your way to
> misinterpret ~anything said to you and/or to put/steer it into the
> context that was obviously not intended.  If talking to you requires
> math like precision in specifying every tiny detail then expect people
> to dissmiss you and your arguments regardless of whatever technical
> merits they might have.
> 
> 

Subprograms are not the invention of MSDOS and predate them. This
feature was available in other OSs like BeOS. atexit() as a mechanism
can be newer.

>> atexit-for-dlclose is already done in C++ behind the scenes for Objects
>> and nobody calls it MSDOS-like environment (even if it is, it's not a
>> bad design).
> 
> Two can play that game... What does that sentence mean?  Which c++
> implementation are you talking about?  What specific aspect of that
> implementation do you refer to as atexit-for-dlclose?  Please provide
> specific examples.
> 
> 

The already linked page from Itanium C++ ABI documents this:

 3.3.6.3 Runtime API

    Object construction:

    After constructing a global (or local static) object, that will
require destruction on exit, a termination function is registered as
follows:
    extern "C" int __cxa_atexit ( void (*f)(void *), void *p, void *d );
    This registration, e.g. __cxa_atexit(f,p,d), is intended to cause
the call f(p) when DSO d is unloaded, before all such termination calls
registered before this one. It returns zero if registration is
successful, nonzero on failure.

Technically atexit() != __cxa_atexit(), but the "atexit-registered
function" mechanism is in place and defined for early DSO unload in C++.

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to