What is the difference between std::quick_exit and std::abort and why was std::quick_exit needed?

Solution 1:

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.

Solution 2:

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.)

Solution 3:

std::abort will terminate your application without calling any functions registered using "at_exit/at_quick_exit". On the other hand, std::quick_exit will, as you pointed out, call the functions registered using std::at_quick_exit.

std::abort typically aborts your application, this should be called when some abnormal situation happens and your application has to be closed without doing any cleanups. From the std::abort documentation:

Causes abnormal program termination unless SIGABRT is being caught by a signal handler passed to signal and the handler does not return.

When you want to perform some cleanups, std::quick_exit will be more appropiate. This last function also lets you stop your application gracefully, since it ends up calling std::_Exit instead of signaling a signal like std::abort(which signals SIGABRT, making the application stop abnormally).

std::exit allows you to exit your application gracefully, while still cleaning up automatic, thread local and static variables. std::quick_exit does not. That's why there is a "quick_" in its name, it's faster since it skips the clean up phase.

Therefore, there is an actual semantic difference between both functions. One stops the application abnormally, and the other performs a gracefull exit, allowing you to do some clean ups.