change the exit status of a C/C++ program during atexit callback - c++

I'm looking for a way to change the exit status of a C/C++ program during an atexit callback sequence.
I'm develping some C++ code that registers a book keeping function with atexit. If the program terminates as a result of an exit() call, this book keeping function prints a message if the data was left in an incomplete state. If this is the case, I want to make sure that the exit status of the program is nonzero. This is probably going to be true anyway, but it's also possible to call exit(0).
One solution is to call exit(-1) within the book keeping function that I've registered with atexit. This seems to work, but I think it's also undefined behavior. Does anyone know if this is correct? It's also unclear if this would terminate the atexit callback chain, which would be bad if there's another critical function registered with atexit.

On POSIX systems, it is allowed to call _exit from within an atexit handler, however doing so means that any other atexit handler is not called.
Since atexit handlers are called in the reverse order of registration, have the first registered handler read a global variable and, if it's not set to some initial sentinel value, call _exit with that value. Then any other handlers you register can modify that global if they want to override the exit value passed to exit.
For example:
#define EXIT_DEFAULT 0xffff
int exit_override = EXIT_DEFAULT;
void override_exit(void)
{
if (exit_override != EXIT_DEFAULT) _exit(exit_override);
}
void handler1(void)
{
if (some_error_condition) exit_override = 1;
}
int main()
{
atexit(override_exit);
atexit(handler1);
// do something that might call exit
return 0;
}

Related

How to exit a program with mixed C/C++ cleanly

I'm interfacing a C program (main() is in C) with C++. At some points in my code I want to stop execution of the program. Now I'd like to know, how can I do this cleanly?
At the moment I call std::terminate() but more out of a lack of better ideas. The main thing that bugs me isn't even that I'm not freeing the memory (because it's freed anyway on program termination, right?) but that the MSVS Just-in-time Debugger pops up and I get an ugly error message about terminating the runtime in an unusual way.
EDIT: As this has caused confusion: Returning from main() with return 0 is not possible in this case.
If you concern about cleaning up and invoking destuctors then
exit(EXIT_SUCCESS); // or EXIT_FAILURE
is the best choice between exit, terminate and abort.
Function exit calls descructors and cleans up the automatic storage objects (The object which declared in the global scope). It also calls the functions passed to atexit.
Function abort is useful for abnormal exits and will not clean up anything. It doesn't call the functions passed to atexit.
Function terminate does not exist in C. It's useful when you have an exception and you can't handle it but finishing the program.
main function is where it starts, main function is where it should end usually. If you use return 0; it indicates succesful exit.
int main(void) {
//init
//do stuff
//deinit
return 0; // bye bye
}
You could also use exit(0);, but if your exit points are scattered all over the place it makes things harder to debug.

how to exit from a function but not from main()

Does C/C++ support terminating a program from a subroutine function i.e not main?
So far I only found that exit and abort allow a user to terminate current function or process.
If I'm not in main function, is there a way to terminate the whole program?
If you are not in main() and in other function then also you can call exit() or abort() it will terminate your whole process.
where exit() will do required clean up where abort() will not perform that.
exit(0) or exit(1)
If this is 0 or EXIT_SUCCESS, it indicates success.
If it is EXIT_FAILURE, it indicates failure.
ref: See here
since you're talking C++, consider std::terminate
u now, for “Does C/C++ support terminating a program from a subroutine function i.e not main?”
by default std::terminate calls abort, but this is configurable by installing a handler via std::set_terminate
void exit (int status)
Above method 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.
And after that Control is returned to the host environment.
As it terminates the calling process, becuase your function is part of same process, so using exit() in that will terminate the program.
It can only be possible if you called that function from main function. And from that function from which you want to terminate the program return a value for terminating the program for example -1.
Example:
void main()
{
//Call to a function
int i = functionFromMain();
if(i == -1)
{
//Terminate Program
}
}

How do I detect if a custom terminate() handler is installed?

My code is compiled as a Windows DLL with Visual C++. I want to log rare cases when terminate() is being called, so I set my terminate() handler in the library initialization function and the latter is called by the user code before using my library. My handler writes to the log and calls abort() emulating the default terminate() behavior.
The problem is the user code might also be written in C++ and use the very same C++ runtime version and so share the terminate() handler with my library. That code might also want to alter the terminate() handler to have their logging. So they would call set_terminate(), then load and initialize my library and my library would also call set_terminate() and override their terminate() handler and that will be very hard for them to detect since the terminate() handler is the last thing they would test I suppose.
So I want the following. Inside the library initialization function I will retrieve the current terminate() handler, find whether it is a standard one, then if it happens to be a non-standard one, I will store its address and later (if needed) my terminate() handler will write into the log and then forward the call to that custom terminate() handler.
Is it possible to find if a terminate() handler currently installed is a default one or a custom one?
Do it via RAII like this:
class terminate_scope
{
public:
terminate_function _prev;
terminate_scope(terminate_function f = NULL){
_prev = set_terminate(f);
}
~terminate_scope(){
set_terminate(_prev);
}
};
To use:
void MyFunctionWantsOwnTerminateHandler(){
terminate_scope termhandler(&OwnTerminateHandler);
// terminate handler now set
// All my code will use that terminate handler
// On end of scope, previous terminate handler will be restored automatically
}
You can have the terminate handler chain the previous one if you are absolutely sure you need to.
MSDN vaguely says that
If no previous function has been set, the return value (of set_terminate) may be used to restore the default behavior; this value may be NULL;
and the same for _get_terminate. I find it not really helpful, because if the returned value is not NULL, still there is no guarantee that it is a valid terminate handler. One possible solution is to use GetModuleHandleEx with GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS to find out if the address returned by set_terminate is a valid address in any module.

About the exit() function in C++

The getche() function doesn't terminate the program properly, so I want to try exit(int status) function. How does it work in Turbo C++ programming language? I cannot understand the explanation in related help modules and I seek for a better explanation... E.g. what does function's parameter consist of? Thanks in advance!
Not 100% sure what you mean by this. The parameter to the exit function (the "int status") is a number that gets returned to the shell. Traditionally, this is zero if your program was successful and >0 if the program failed for some reason. The function will clean up various things and then exit your program.
Well. Functions like getch.. usually get a character from the keyboard or standard input. They are sometimes used at the end of programs like this
int main() {
// do many stuff...
// ...
getch();
}
The getch/getche (i don't know what the e stands for in turbo-c++) are then used to give the user the change to see the output of the program, before the terminal windows closes (usually that happens in windows). Note that there is a portable function called getchar in C and C++ that does also do that job (waits for an enter in addition, but that won't cause a harm here).
But it is not used to terminate the program. After a key is pressed, control continues and then after main finished, the program exists. C++ and recent C versions insert a return 0; implicitly after the last statement of the main function (0 stands for "succesful"). This means your main function returns a value of 0 back to the OS. But you can return other values if you write the return explicitly and put another value there. That value is what exit expects. It terminates your program, and returns the given value back to the OS.
int main() {
// some stuff...
exit(42);
// other stuff (note: never reached!)
}
That program will return a value of 42 to the OS. Normally you just return 42; there and it has the same effect (*).
(*) Well, not entirely: If you have local variables, the destructor of those are not called if you use exit. But they are cleanly destructed and destructors are called when you use return n;. Therefor, prefer return n; in main when you can. exit called in other functions than your main will terminate your program too, so it can be required to use that instead, because return there will just return from those specific functions and do not at all terminate the program.
The parameter is an integer status code that is passed back to the invoking shell as the exit status of the process. Exit itself should exit the process an clean up any open resources that your process is using.
The parameter to Exit() is an int that indicates the reason or status of the exiting process.
Boy, that didn't sound good. Let me try again: It's a value that is passed back to either the starting process (the process that used CreateProcess() or ShellExecute() to launch the one that's exiting), or, in the case of a console app a value to the command shell that can be accessed via ERRORLEVEL.
It's typical to set status = 0 if you're exiting normally, another value (that can have meaning if you want to the process that receives it) to indicate errors or problems.
The parameter is an integer status code that is passed back to the invoking shell as the exit status of the process. Exit itself should exit the process an clean up any open resources that your process is using.
More Info on "exit" Function
"exit" function Terminates the process normally, performing the regular cleanup for terminating processes.
First, all functions registered by calls to "atexit" are executed in the reverse order of their registration. Then, all streams are closed and the temporary files deleted, and finally the control is returned to the host environment.
The value supplied as an argument to exit is returned to the operating system ( the host environment) as the program's return code or exit code. By convention, a return code of zero means that the program completed successfully.
Hope this clears your doubt.

What is the difference between exit() and abort()?

In C and C++, what is the difference between exit() and abort()? I am trying to end my program after an error (not an exception).
abort() exits your program without calling functions registered using atexit() first, and without calling objects' destructors first. exit() does both before exiting your program. It does not call destructors for automatic objects though. So
A a;
void test() {
static A b;
A c;
exit(0);
}
Will destruct a and b properly, but will not call destructors of c. abort() wouldn't call destructors of neither objects. As this is unfortunate, the C++ Standard describes an alternative mechanism which ensures properly termination:
Objects with automatic storage duration are all destroyed in a program whose function main() contains no automatic objects and executes the call to exit(). Control can be transferred directly to such a main() by throwing an exception that is caught in main().
struct exit_exception {
int c;
exit_exception(int c):c(c) { }
};
int main() {
try {
// put all code in here
} catch(exit_exception& e) {
exit(e.c);
}
}
Instead of calling exit(), arrange that code throw exit_exception(exit_code); instead.
abort sends a SIGABRT signal, exit just closes the application performing normal cleanup.
You can handle an abort signal however you want, but the default behavior is to close the application as well with an error code.
abort will not perform object destruction of your static and global members, but exit will.
Of course though when the application is completely closed the operating system will free up any unfreed memory and other resources.
In both abort and exit program termination (assuming you didn't override the default behavior), the return code will be returned to the parent process that started your application.
See the following example:
SomeClassType someobject;
void myProgramIsTerminating1(void)
{
cout<<"exit function 1"<<endl;
}
void myProgramIsTerminating2(void)
{
cout<<"exit function 2"<<endl;
}
int main(int argc, char**argv)
{
atexit (myProgramIsTerminating1);
atexit (myProgramIsTerminating2);
//abort();
return 0;
}
Comments:
If abort is uncommented: nothing is printed and the destructor of someobject will not be called.
If abort is commented like above: someobject destructor will be called you will get the following output:
exit function 2
exit function 1
The following things happen when a program calls exit():
Functions registered by the atexit function are executed
All open streams are flushed and closed, files created by tmpfile are removed
The program terminates with the specified exit code to the host
The abort() function sends the SIGABRT signal to the current process, if it is not caught the program is terminated with no guarantee that open streams are flushed/closed or that temporary files created via tmpfile are removed, atexit registered functions are not called, and a non-zero exit status is returned to the host.
From the exit() manual page:
The exit() function causes normal process termination and the value of
status & 0377 is returned to the parent.
From the abort() manual page:
The abort() first unblocks the SIGABRT signal, and then raises that
signal for the calling process. This results in the abnormal termination of the process unless the SIGABRT signal is caught and the signal
handler does not return.
abort sends the SIGABRT signal. abort does not return to the caller. The default handler for the SIGABRT signal closes the application. stdio file streams are flushed, then closed. Destructors for C++ class instances are not, however (not sure on this one -- perhaps results are undefined?).
exit has its own callbacks, set with atexit. If callbacks are specified (or only one), they are called in the order reverse of their registration order (like a stack), then the program exits. As with abort, exit does not return to the caller. stdio file streams are flushed, then closed. Also, destructors for C++ class instances are called.