Differencebetween Std::Quick_Exit and Std::Abort and Why Was Std::Quick_Exit Needed

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

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.

Difference between exit and quick_exit

exit ensures that stream buffers are flushed, closed, etc. Such behavior for quick_exit is not specified by the standard.

With these you can define two ways of quitting an application, one that lets you terminates with full cleaning (made by functions registered with atexit), and the other to let applications terminate more quickly without cleaning too much things (calls to functions registered with at_quick_exit).

What are some practical applications of the quick_exit and at_quick_exit functions?

Basically it exists in C because of C++. The relevant document from WG 14 C standard committe can be found here.

The document was adapted from the paper accepted by the C++ standard. The idea behind quick_exit is to exit the program without canceling all threads and without executing destructors of static objects. C doesn't has language support for such things as "destructors" at all and the thread support library in C is almost nowhere implemented. The at_quick_exit and quick_exit functions have very little to no meaning at all in C.

In C there is a function _Exit that causes normal program termination to occur and control to be returned to the host environment, but is not required to flush open file descriptors, write unbuffered data, close open files, as opposed to exit(). Basically the at_quick_exit and quick_exit functions are facilities build to run custom user handles and then execute _Exit, while atexit is a facility to execute custom handlers upon calling exit().

What should happen if one calls `std::exit` in a global object's destructor?

[basic.start.main]/4:

If std​::​exit is called to end a program during the destruction of an object with static or thread storage duration, the program has undefined behavior.

abort, terminate or exit?

My advice would be not to use any of them. Instead, catch the exceptions you can't handle in main() and simply return from there. This means that you are guaranteed that stack unwinding happens correctly and all destructors are called. In other words:

int main() {
try {
// your stuff
}
catch( ... ) {
return 1; // or whatever
}
}

How to exit a process without any unwinding in C++98?

You can use abort() from <cstdlib>. It sends a SIGABRT to a process and if the signal is not caught the program is terminated without calling any destruction routines like atexit() or any destructors.

More info here: link

Edit: std::quick_exit exits normally, whereas calling abort() results in abnormal termination, don't know if that's a problem.

How to handle quick_exit in a class member thread when `this` becomes a nullptr?

Your code has a race condition.

Time::Time()
{
// ...
m_running = true;
m_worker = std::move(std::thread(std::bind(&Time::Worker, this)));
}

Here tread starts before

std::shared_ptr<Time> time_data(std::make_shared<Time>());

is completed.

Simply thread reaches monitor::Time::HasTimedOut before std::shared_ptr<Time> time_data(std::make_shared<Time>()); is completed.

Spawn thread not in constructor, but in separate method which you will invoke after time_data is assigned.

Anyway it would be better if your Timer do not use time_data global variable at all.

When is it better to use exit() vs exceptions in c++?

exit() is fine for small programs. For larger programs, there are several problems with it. First, not all errors should terminate a program - often it can recover.

The 2nd problem: even if you want to terminate, it is difficult to write a single clean_up() function that would take care of all resources allocated in various parts of the program. This what RAII in C++ is for. exit() is incompatible with RAII as it does not call destructors, except for global or static objects.

The 3rd problem: at the point of error detection, you often cannot construct an error message meaningful to the end user, but it is possible to construct such error message when an exception is caught.

Usually, the dilemma is different: the alternative to exceptions is using return codes to indicate errors. There are multiple trade-offs between exceptions and return codes, and hundreds of articles are devoted to this topic. It is too large to analyze within this answer.



Related Topics



Leave a reply



Submit