Created on 2018-03-15.00:00:00 last changed 4 months ago
[ 2024-07-26; Jonathan comments ]
In C89 and C99 the spec for `exit` in C said "If more than one call to the exit function is executed by a program, the behavior is undefined." Since C11 that was updated to also talk about `at_quick_exit`, saying "If a program calls the `exit` function more than once, or calls the `quick_exit` function in addition to the `exit` function, the behavior is undefined." The spec for `quick_exit` is similar.
That answers most of the questions here. An `atexit` or `at_quick_exit` handler cannot call `exit` or `quick_exit`, because if a handler is running then it means that `exit` or `quick_exit` has already been called, and calling either of them again would be undefined. It doesn't matter whether an `atexit` handler installs an `at_quick_exit` handler, because once `exit` handlers start running it would be undefined to call `quick_exit`, and vice versa. So you should never have a situation where both sets of handlers are running.
There is a suggestion to relax this in POSIX so that calling `exit` or `quick_exit` again from other threads would not be UB but would just block until the process exits, which should happen eventually assuming exit handlers make forward progress (calling `exit` or `quick_exit` from a handler would still be UB).
Why does C++ not make it undefined to call `exit` twice? Can we change that?
[ 2018-04-02 Priority set to 3 after discussion on the reflector. ]
[ 2018-04-02, Jens comments ]
Any potential wording should carefully take [basic.start] into account, and maybe should actually be integrated into the core wording, not the library wording.
It's unclear how different termination facilities in C++ interact (and how they interact with the C termination facilities). Individually some of these functions try to handle corner cases, but hilarity ensues when combined with each other. As a simple example, can an atexit handler call exit? If not, can it call quick_exit, and can then at_quick_exit handler call exit? Is it possible to install an atexit handler from an at_quick_exit, without strongly happens before, while handling a separate atexit handler (and what happens then)?
The termination handlers and termination conditions I collected:returning from main calls atexit handlers.
atexit / exit
at_quick_exit / quick_exit
set_terminate
violating noexcept and other things that call std::terminate (see [except.terminate])
violating exception specification
parallel algorithms leaving with uncaught exception
some std::signal such as SIGTERM, SIGSEGV, SIGINT, SIGILL, SIGABRT, and (maybe?) SIGFPE.
set_unexpected (now a zombie)
unexpected_handler (now a zombie)
What's unclear is:
Is termination handling a DAG?
Which thread(s) are termination handlers called on?
Is program termination Turing complete?
I've written a sample program which exercises some of this, see here.
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-07-26 09:01:45 | admin | set | messages: + msg14266 |
2018-04-03 18:56:45 | admin | set | messages: + msg9798 |
2018-04-03 18:56:45 | admin | set | messages: + msg9797 |
2018-03-15 00:00:00 | admin | create |