C++11 introduces a new way of finishing program execution—std::quick_exit
.
Quoting the N3242 18.5 (p. 461):
[[noreturn]] void quick_exit(int status) noexcept;
Effects: Functions registered by calls to
at_quick_exit
are called in the reverse order of their registration, except that a function shall be called after any previously registered functions that had already been called at the time it was registered. Objects shall not be destroyed as a result of callingquick_exit
. If control leaves a registered function called byquick_exit
because the function does not provide a handler for a thrown exception,terminate()
shall be called. [ Note:at_quick_exit
may call a registered function from a different thread than the one that registered it, so registered functions should not rely on the identity of objects with thread storage duration. — end note ] After calling registered functions,quick_exit
shall call_Exit(status)
. [ Note: The standard file buffers are not flushed. See: ISO C 7.20.4.4. — end note ]
As the definition of std::abort(void)
and std::_Exit(int status)
differ only in ability to pass the status to the parent process, it raises my question.
Does it mean that the only difference in semantics between std::quick_exit
and std::abort
are that std::quick_exit
calls functions registered using std::at_quick_exit
and allows to set the returned status?
What was the rationale for introducing this function?
std::abort()Causes abnormal program termination unless SIGABRT is being caught by a signal handler passed to std::signal and the handler does not return.
abort() -- Stop a Program The abort() function causes an abnormal end of the program and returns control to the host environment. Like the exit() function, the abort() function deletes buffers and closes open files before ending the program.
If you call abort anywhere in a program, no destructors are called, not even for variables with a global scope.
There's a good write-up available here, I'll just summarize it. This feature was added to specifically deal with the difficulty of ending a program cleanly when you use threads. By nature, the exit is started by a highly asynchronous event, the user closing the user interface, the admin shutting down the machine, etcetera. This happens without regard to the state of the threads the program started, they are almost always in a highly unpredictable state.
In an ideal world, the program's main() function asks the threads to exit, typically by signaling an event, waits for the threads to end and then exits main() for a clean shutdown through exit(). That ideal is however very hard to achieve. A thread could be buried deep inside a system call, say, waiting for some I/O to complete. Or it is blocking on a synchronization object that needs to be signaled by another thread in the right order. The outcome is rarely pleasant, real programs often deadlock on exit. Or crash when the shutdown order is unexpected.
There's a simple and very tempting workaround for this problem: call _exit() instead. Kaboom, program ended, the operating system brooms up the shrapnel. But clearly without any cleanup at all, very messy sometimes with artifacts like a half-written file or an incomplete dbase transaction.
std::quick_exit() offers the alternative. Similar to _exit() but with still the option to execute some code, whatever was registered with at_quick_exit.
The rationale for std::quick_exit
is discussed in N1327 and N2440. The key differences between quick_exit
, _Exit
, and exit
concerns the handling of static destructors and flushing critical information to stable storage:
std::_Exit
: doesn't execute static destructors or flush critical IO.std::exit
: executes static destructors and flushes critical IO.std::quick_exit
: doesn't execute static destructors, but does flush critical IO.(As mentioned, std::abort
just sends SIGABRT
.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With