What are the possible effects of a unavoidable call of abort()? - c++

In cppreference abort, we have
Destructors of variables with automatic, thread local and static storage durations are not called. Functions passed to std::atexit() are also not called. Whether open resources such as files are closed is implementation defined.
I'm bit confused about the terminology and contradiction of the abort term that "closes" my program and from the description of that function which it says that destructors and open resources possibly are not called/closed, respectively. So, is it possible that my program remains running and it has some memory leak or resources still opened after a call to abort()?

It's like killing a person. They won't have a chance to pay any outstanding bills, organize their heritage, clean their apartment, etc.
Whether any of this happens is up to their relatives or other third parties.
So, usually things like open files will be closed and no memory will be leaked because the OS takes care of this (like when the police or so will empty the apartment). There are some platforms where this won't happen, such as 16 bit windows or embedded systems, but under modern windows or Linux systems it will be okay.
However, what definitely won't happen is that destructors are run. This would be like having the to-be-killed person write a last entry into their diary and seal it or something - only the person itself knows how to do it, and they can't when you kill them without warning. So if anything important was supposed to happen in a destructor, it can be problematic, but usually not dramatically - it might be something like that the program created a Temporary file somewhere and would normally delete it on exiting, and now it can't and the file stays.
Still, your program will be closed and not running anymore. It just won't get a chance to clean up things and is therefore depending on the OS to do the right thing and clean up the resources used by it.

Functions passed to std::atexit() are also not called. Whether open resources such as files are closed is implementation defined.
This means the implementation gets to decide what happens. On any common consumer operating system, most objects associated with your process get destroyed when your process exits. That means you won't leak memory that was allocated with new, for example, or open files.
There might be uncommon kinds of objects that aren't freed - for example, if you have a shared memory block, it might stay around in case another process tries to access it. Or if you created a temporary file, intending to delete it later, now the file will stay there because your program isn't around to delete it.

On Unix, calling abort() effectively delivers a SIGABRT signal to your process. The default behavior of the kernel when that signal is delivered is to close down your process, possibly leaving behind a core file, and closing any descriptors. Your process's thread of control is completely removed. Note that this all happens outside any notion of c++ (or any other language). That is why it is considered implementation defined.
If you wish to change the default behavior, you would need to install a signal handler to catch the SIGABRT.

Related

C++ graceful shutdown best practices

I'm writing a multi-threaded c++ application for *nix operating systems. What are some best practices for terminating such an application gracefully? My instinct is that I'd want to install a signal handler on SIGINT (SIGTERM?) which stops/joins my threads. Also, is it possible to "guarantee" that all destructors are called (provided no other errors or exceptions are thrown while handling the signal)?
Some considerations come to mind:
designate 1 thread to be responsible for orchestrating the shutdown, eg, as Dithermaster suggested, this could be the main thread if you are writing a standalone application. Or if you are writing a library, provide an interface (eg function call) whereby a client program can terminate the objects created within the library.
you cannot guarantee destructors are called; that is up to you, and requires carefully calling delete for each new. Maybe smart pointers will help you. But, really, this is a design consideration. The major components should have start & stop semantics, which you could choose to invoke from the class constructor & destructor.
the shutdown sequence for a set of interacting objects is something that can require some effort to get correct. E.g., before you delete an object, are you sure some timer mechanism is not going to try calling it in few micro/milli/seconds later? Trial and error is your friend here; develop a framework which can repeatedly & rapidly start and stop your application to tease out shutdown related race-conditions.
signals are one way to trigger an event; others might be periodically polling for a known file, or opening a socket and receiving some data on it. Either way, you want to decouple the shutdown sequence code from the trigger event.
My recommendation is that the main thread shut down all worker threads before exiting itself. Send each worker an event telling it to clean up and exit, and wait for each one to do so. This will allow all C++ destructors to run.
Regarding signal management, the only thing you can portably and safely do inside a signal handler is to write to a variable of type sig_atomic_t (possibly volatile-qualified) and return. In general, you cannot call most functions and must not write to global memory. In other words, the handler should just set a flag to be tested inside your main routine, at some point you find appropriate, and the action resulting from the signal itself should be performed from there.
(Since there might be blocking I/O involved, consider studying POSIX Thread Cancellation. Your Unix clone (most notably Linux) might have peculiarities with respect to this and to the above.)
Regarding destructors, no magic is involved. They will be executed if control leaves a given scope through any means defined in the language. Leaving a scope through other means (for example, longjmp() or even exit()) does not trigger destructors.
Regarding general shutdown practices, there are divergent opinions on the field.
Some state that a "graceful termination", in the sense of releasing every resource ever allocated, should be performed. In C++, this usually means that all destructors should be properly executed before the process terminates. This is tricky in practice and often a source of much grief, specially in multithreaded programs, for a variety of reasons. Signals further complicate things by the very nature of asynchronous signal dispatching.
Because most of this work is totally useless, some others, like me, contend that the program must just terminate immediately, possibly shortly after undoing persistent changes to the system (like removing temporary files or restoring the screen resolution) and saving configuration. An apparently tidier cleanup is not only a waste of time (because the operating system will clean up most things like allocated memory, dangling threads and open file descriptors), but might be a serious waste of time (deallocators might touch paged out memory, uselessly forcing the system to page them in just for releasing them soon after the process terminates, for example), not mentioning the possibility of deadlocks being originated from joining threads.
Just say no. When you want to leave, call exit() (or even _exit(), but watch out for unflushed I/O) and that's it. More annoying than slow starting programs are slow terminating programs.

Should I always call Release on COM pointers when my program terminates?

I know that modern Windows versions reclaim memory that was previously acquired with malloc, new and the like, after program termination, but what about COM objects? Should I call obj->Release() on them on program's exit, or will the system do this for me?
My guess it: it depends. For out of process COM, I should probably always call Release(), but for in-process COM, I think it really doesn't matter, because the COM objects die after program termination anyway.
If you're in the process itself then yes you should as you might not know where the server is and the server could be out of proc. If you're in a DLL it becomes more complicated.
In a DLL you should UNLESS you receive a DLL_PROCESS_DETACH notification, in which case you should do absolutely nothing and just let the application close. This is because this notification is called during process teardown. As such it is too late to clean up at that point. The kernel may have already reclaimed the blocks you call release on.
Remember as a DLL writer there is nothing you can do if the process exits ungracefully, you can only do what you can within reason to clean up after yourself in a graceful exit.
One easy solution is to use smart COM Pointers everywhere, the ATL and WRL have implementations that work nicely and make it so you don't have to worry about it for the most part. Even if these are stored statically their destructors will be called before process teardown or DLL unload, thus releasing safely at a time when it is safe to do so.
So the short answer is If you can e.g. you should always call release if it is safe to do so. However there are times when it is not and you should most definitely NOT do anything.
Depending on the implementation of the underlying object, there may or may not be a penalty. The object may have state that persists beyond process shutdown. A persistent lock in a local database is the easiest example that comes to mind.
With that in mind, I say it's better to call Release just in case.
in-process COM object will die with the process
out-of-process reference will be released on timeout
poorly designed servers and clients might remain in bad state holding pointers to objects (typically proxies), that are not available any longer, being unable to see they are dead. being unable to get rid of them
it is always a good idea to release the pointers gracefully
If you don't release COM pointers properly, and COM activity included marshaling, you are very likely to have exceptions in CoUninitialze which are both annoying and/or can end up showing process crash message to the user.

c++ should i bother deleting pointers to application lifetime variables?

I have a few "global" constructs that are allocated with new and are alive the entirety of the applications life span.
Should i bother calling delete on the pointers just before the application finishes?
Doesn't all the of the applications memory get reclaimed after it closes anyway?
Edit For Clarity. I am only talking about not calling delete for lifetime objects who "die" right as the program is closing.
Technically, yes, the memory is reclaimed. But unless you use delete the destructors of those objects are not run and their side effect is not applied. This might lead to a temporary file not deleted or a database change not committed depending on what those destructor were meant to do.
Also don't forget Murphy. Now the code for managing those objects is used as you describe (objects have to persist for the life of the program) but later you might want to reuse the code so that it is run multiple times. Unless it can deal with recreating objects properly it will be leaking objects.
It is always good practice to clean up everything, although the memory is reclained these objects might have other resources allocated (shared memory, smeaphores etc) that should be cleaned up, probably by the objects destructors.
If you do not want to call delete use shared pointers to hold these resources, so that they are cleaned up correctly when the application exits.
How are you testing your application? Not cleaning up might hinder development of a decent test harness. Tests of the application might want a way of spoofing a shutdown and restart.
There is more to cleaning up that simple releasing memory.
No, don't write/debug/maintain code to do something that the OS is already very good at.
Unless there are specific reasons to the contrary, (eg. outstanding transactions to be commited, files to flush, connections to be closed), I don't bother writing code to do something that the OS is going to do anyway. If a dtor does nothing special, why bother calling it?
Many developers put in a lot of effort into deleting/destroying/freeing/terminating stuff at app close time - a load of effort to avoid some spurious 'leak report' on app shutdown from a memory manager that is itself about to be destroyed.
I think you're probably right, but I personally would consider it poor coding and bad practise to rely on the system and would ensure my code always tidied properly whe shutting down.
There is no one right answer. Most of the time, it probably doesn't
matter, but there are destructors which do something important, beyond
just freeing memory (I have one which deletes temporary files), which
argues in favor of cleanup; on the other hand, destructing such objects
may lead to order of destruction issues, if the objects are used by
destructors of other objects. My general rule is to not destruct,
unless the destructor does something more than just free memory, but
others may prefer a different set of defaults.
In addition to the destructors not being executed (as sharptooth pointer out), it's also worthwhile to delete global objects to make memory checkers happy. Especially if your code is in a shared library - you don't want to clutter their memory checker (say, Valgrind) output just because you didn't delete properly.
.. then there's those cases where you definitely don't want the dtor's called at all before the OS terminates the process, eg:
1) When the dtor does not work properly because it tries to terminate a thread, fails and blocks on the thread handle or other signal, (the perennial 'join/waitFor' deadlock) - the cause off 99% of all household 'my app will not close down cleanly' posts.
2) When the dtor does not work properly because it's just bad anyway and buried in a library.
3) Where the memory must outlive the process threads else there will be segfaults/AV on close, (eg. pools of buffer objects that threads may well be writing to at close time).
4) Any other 'special cases' where the destruction of the object/s has to be left to the OS.
There are so many 'special cases' that I regard 'cleaning up' shutdown code as the special case.

Why is it important to call destructors at program termination?

If you check this link http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=107
it's written:
"For example, the abort() and exit() library functions are never to be used in an object-oriented environment—even during debugging—because they don't invoke objects' destructors before program termination."
Why does the destructor need to be called when one calls exit? (Since the OS guarantees memory will be reclaim whenever a program exits, right?)
Destructors can, and often do, other operations besides freeing memory and/or resources. They are often used to make certain other guarantees such as user data is written to a file or non-process specific resources are in a known state. The OS won't do these types of operations on exit.
That being said, any program which relies on these types of actions is fundamentally flawed. Use of exit and abort are not the only ways destructors are avoided. There are many other ways a destructor can be circumvented. For example user forcable terminating the process or a power outage.
I definitely disagree with the use of never in the quoted passage. I can think of at least one situation where you absolutely don't want destructors executing: corrupted memory. At the point you detect corrupted memory you can no longer make any guarantees about the code in your process, destructors included. Code which should write data to a file might delete / corrupt it instead.
The only safe thing to do when memory corruption is detected is to exit the process as fast as possible.
First I will like to advice that "Don't believe anything blindly you have read."
Probably as JaredPar said the destructor may doing some logging things and closing of OS resource handle things. In case you call abort or exit these things will never happen.
But I certainly do not agree with the quote at all. Abort is the best and the fastest way of finding the programming errors in the development cycle. As a developer you certainly don't put abort blindly everywhere in the code, but on the condition you know that should have never happened. You put abort when you know that the other programmer or you have messed up somewhere in the code and it's better to stop than to handle the error. I have gone through a situation where abort has really saved my #$$.

should we use exit in C++?

According to C++ reference
exit terminates the process normally, performing the regular cleanup
for terminating programs.
Normal program termination performs the following (in the same order):
Objects associated with the current thread with thread storage
duration are destroyed (C++11 only). Objects with static storage
duration are destroyed (C++) and functions registered with atexit are
called. All C streams (open with functions in ) are closed
(and flushed, if buffered), and all files created with tmpfile are
removed. Control is returned to the host environment.
Note that objects with automatic storage are not destroyed by calling
exit (C++).
as far as i know, when the process terminated, all the storage used by the process are reclaimed, so what's the impact that objects with automatic storage are not destroyed?
If those destructors are not called, their side effects don't happen: Freeing resources in other processes, deleting temporary files outside that folder, flushing non-c stream files, etc etc etc
The problem is the fact not everything you might somehow take ownership of is listed in the standard as getting cleaned up.
For example, many programs and libraries do things like create lock files, start background processes, change system settings, and so on. These may be cleaned up by the OS if you call exit, but they aren't required to be. Failing to release these could have effects ranging from being unable to restart the program (typical of lock files) to total system failure (less likely, but possible in some cases).
True, on-topic anecdote. I used to use OIS, an input library, for my project. Every time I killed my program in the debugger, key repeat was broken system-wide, because OIS 'temporarily' disabled it in Linux. I fixed it by changing settings (and later dumping OIS entirely), but this illustrates very well the sort of issues you might run into calling exit before you have cleaned up your environment yourself.
In C++ you should preferably use std::terminate rather than exit or abort to do an orderly fatal error exit, because code that you're using may have installed a terminate handler to do critical cleanup.
The default std::terminate handler calls abort.
The stack is not unwound.
Re
” what's the impact that objects with automatic storage are not destroyed?
Because destructors are not called, cleanup that they might do is not performed. For example, in Windows a console window might become unusable if it has a custom text buffer. Temporary files might be left on disk. Helper processes might not be shut down. And so on.
This must be weighted against the possibility of nasty things happening if general cleanup is attempted, e.g. because an assertion has fired, showing that some fundamental assumption about the process state doesn't hold.