This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
what is the purpose of atexit function?
In UNIX at least: I'm aware that C/C++ can register a number of functions to be called at the exit of main - exit handlers. Thee functions to be called can be registered, in reverse order, using:
int atexit(void (*func) (void));
I'm having trouble determining how this would be useful though. The functions are void/void and global, so they are unlikely to have access to many variables around the program unless the variables are also globals. Can someone let me know the kinds of things you would do with exit handlers?
Also, do exit handlers work the same way on non-UNIX platforms since they're part of an ANSI C specification?
You can perform cleanup for global objects in a atexit handler:
static my_type *my_object;
static void my_object_release() { free(my_object); }
my_type *get_my_object_instance()
{
if (!my_object)
{
my_object = malloc(sizeof(my_type));
...
atexit(my_object_release);
}
return my_object;
}
If you want to be able to close over some variables in an atexit-like handler, you can devise your own data structure containing cleanup function/parameter pairs, and register a single atexit handler calling all the said functions with their corresponding arguments.
Exit handler allows a library to do shutdown cleanup (thus of global data structure) without the main program being aware of that need. Two examples of things I've done in an exit handler:
restoring tty flags
closing correctly a network connection so that the peer hadn't to wait a time out
Your probably can think of other use.
The most obvious problem that an atexit handler solves, is tidy up for global objects. This is a C feature and of course C doesn't have automatic deallocation like C++. If you have access to the implementation of main you can write your own such code, but otherwise atexit can be helpful.
Read this blog post on Start and Termination in C++:
When a program is terminating it needs to do some finishing touches
like saving data to a file that will be used in the next session. In
this light each program has a particular set of things to do depending
on the purpose of the program (when closing). Any of such things done
is done by one of the functions whose pointer would be argument to the
atexit function.
The purpose of the atexit function is to register (record in memory)
the functions for these finishing touches. When the atexit function
executes using any of the pointers to these functions as argument the
pointed function is registered. This has to be done before the C++
program reaches its termination phase.
Read more: http://www.bukisa.com/articles/356786_start-and-termination-in-c#ixzz1WdWVl4TF
Related
This question already has answers here:
How to avoid using printf in a signal handler?
(8 answers)
Closed 2 years ago.
I have a code that looks like this:
//global variables
void signal_handler() {
//deallocation of global variables
free(foo);
close(foo_2);
exit(0);
}
int main () {
signal(SIGINT, signal_handler);
//irrelevant code
}
As you can see, I changed the CTRL+C interruption to execute the signal_handler function once instead of killing the process right away. I read somewhere that some functions like might be free are not async-safe and would NOT execute in the signal_handler but I'm not sure about that.
Can I execute functions like free, close, exit or even pthread_join in a signal handler?
No. Only functions listed in man 7 signal-safety are safe to call inside a signal handler.
close is listed and should be safe. free is not. For reasons why you would have to look at its source code (it contains locks). exit is not safe because it can call arbitrary cleanup handlers. You have _exit which exits abruptly without the cleanup.
You techincally can compile a program that calls such functions in a signal handler, nothing stops you from doing that. However it will result in undefined behavior if the function you are trying to execute is not async-signal-safe. It's not like unsafe function would just "NOT execute" as you say, they very well could, but that'd still be undefined behavior.
A list of async-signal-safe functions is documented in man 7 signal-safety. The close() function is safe, while free() and phtread_join() are not. The exit() function is also not safe to call from a signal handler, if you wish to exit from such context you will have to do so using _exit() instead.
The only way to safely call a function that is not async-signal-safe when receiving a signal is to "remember" that you have to call it (for example setting a global variable) and then do so after returning from the signal handler.
Short answer is no:
7.1.4 Use of library functions
...
4 The functions in the standard library are not guaranteed to be reentrant and may modify
objects with static or thread storage duration.188)
188) Thus, a signal handler cannot, in general, call standard library functions
C 2011 Online Draft
Real-world example of the consequences - I worked on a system that communicated with an Access database. There was a signal handler that tried to write an error message to the console with fprintf, but somehow during the signal handling process stderr got mapped to the .mdb file that stored the database, overwriting the header and ruining the database beyond repair.
There's honestly not a whole lot you can do in a signal handler other than set a flag to be checked elsewhere.
Can I execute free() or close() in a signal handler?
You definitely should not. See signal(7) and signal-safety(7)
In practice, it might work like you want perhaps more than half of the time. IIRC, the GCC compiler is doing like you want to do, and it usually works.
A better approach is to use some write(2) to a pipe(7) (from inside your signal handler) and from time to time check that pipe (in your main program) with poll(2) or related things.
Or you could set some volatile sigatomic_t flag; (perhaps it should be also _Atomic) in your signal handler, and check that flag elsewhere (in the main program, outside of signal handlers).
Qt is explaining that better than I could do in a few minutes.
On Linux, see also signalfd(2) and eventfd(2).
Taken from: https://www.gnu.org/software/libc/manual/html_node/Nonreentrancy.html
For example, suppose that the signal handler uses gethostbyname. This function returns its value in a static object, reusing the same object each time. If the signal happens to arrive during a call to gethostbyname, or even after one (while the program is still using the value), it will clobber the value that the program asked for.
I fail to see how the above scenario is non-reentrant. It seems to me that gethostbyname is a (read-only) getter function that merely reads from memory (as opposed to modifying memory). Why is gethostbyname non-reentrant?
As the word says, reentrancy is the capability of a function to be able to be called again while it is being called in anothe thread. The scenario you propose is the exact place in which reentrancy is exercised. asume the function has some static or global variable (as the gethostbyname(3) function does) As the return buffer for the structure is being written by one, the other call can be overwriting it to completely destroy the first writing. When the in execution instance of the function (the interrupted one, not the interrumpting one) gets control again, all it's data has been overwritten by the interrupting one, and destroyed it.
A common solution to solve this problem with interruptions is to disable interrupts while the function is executing. This way it doesn't get interrupted by a new call to itself.
If two threads call the same piece of code, and all the parameters and local variables are stored in the stack, each thread has a copy of its own data, so there's no problem in calling both at the same time, as the data they touch is in different stacks. This will not happen with static variables, being those local scope, compilation unit scope or global scope (think that the problem comes when calling the same piece of code, so everywhere one call has access to, the other has also)
Static data, like buffers (look at stdio buffered packages) etc. means in general, the routines will not be reentrant.
I've come across at_quick_exit and quick_exit while going over stdlib.h and looking for functions that I haven't implemented.
I don't understand the point of having these two functions. Do they have any practical usage?
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().
They essentially have no practical usage. The intent seems to be that a function that may have significant nontrivial atexit handlers could use quick_exit to exit with just a minimal subset of such handlers (that it defines by calling at_quick_exit) being called, under conditions where calling all the atexit handlers may not be safe. It may also be called from a signal handler, but it doesn't seem like there'd be anything meaningful you could do from the at_quick_exit handlers in that case.
There is question about using exit in C++. The answer discusses that it is not good idea mainly because of RAII, e.g., if exit is called somewhere in code, destructors of objects will not be called, hence, if for example a destructor was meant to write data to file, this will not happen, because the destructor was not called.
I was interested how is this situation in C. Are similar issues applicable also in C? I thought since in C we don't use constructors/destructors, situation might be different in C. So is it ok to use exit in C? For example I have seen following functions sometimes used in C:
void die(const char *message)
{
if(errno) {
perror(message);
} else {
printf("ERROR: %s\n", message);
}
exit(1);
}
Rather than abort(), the exit() function in C is considered to be a "graceful" exit.
From C11 (N1570) 7.22.4.4/p2 The exit function (emphasis mine):
The exit function causes normal program termination to occur.
The Standard also says in 7.22.4.4/p4 that:
Next, all open streams with unwritten buffered data are flushed, all
open streams are closed, and all files created by the tmpfile function
are removed.
It is also worth looking at 7.21.3/p5 Files:
If the main function returns to its original caller, or if the exit
function is called, all open files are closed (hence all output
streams are flushed) before program termination. Other paths to
program termination, such as calling the abort function, need not
close all files properly.
However, as mentioned in comments below you can't assume that it will cover every other resource, so you may need to resort to atexit() and define callbacks for their release individually. In fact it is exactly what atexit() is intended to do, as it says in 7.22.4.2/p2 The atexit function:
The atexit function registers the function pointed to by func, to be
called without arguments at normal program termination.
Notably, the C standard does not say precisely what should happen to objects of allocated storage duration (i.e. malloc()), thus requiring you be aware of how it is done on particular implementation. For modern, host-oriented OS it is likely that the system will take care of it, but still you might want to handle this by yourself in order to silence memory debuggers such as Valgrind.
Yes, it is ok to use exit in C.
To ensure all buffers and graceful orderly shutdown, it would be recommended to use this function atexit, more information on this here
An example code would be like this:
void cleanup(void){
/* example of closing file pointer and free up memory */
if (fp) fclose(fp);
if (ptr) free(ptr);
}
int main(int argc, char **argv){
/* ... */
atexit(cleanup);
/* ... */
return 0;
}
Now, whenever exit is called, the function cleanup will get executed, which can house graceful shutdown, clean up of buffers, memory etc.
You don't have constructors and destructors but you could have resources (e.g. files, streams, sockets) and it is important to close them correctly. A buffer could not be written synchronously, so exiting from the program without correctly closing the resource first, could lead to corruption.
Using exit() is OK
Two major aspects of code design that have not yet been mentioned are 'threading' and 'libraries'.
In a single-threaded program, in the code you're writing to implement that program, using exit() is fine. My programs use it routinely when something has gone wrong and the code isn't going to recover.
But…
However, calling exit() is a unilateral action that can't be undone. That's why both 'threading' and 'libraries' require careful thought.
Threaded programs
If a program is multi-threaded, then using exit() is a dramatic action which terminates all the threads. It will probably be inappropriate to exit the entire program. It may be appropriate to exit the thread, reporting an error. If you're cognizant of the design of the program, then maybe that unilateral exit is permissible, but in general, it will not be acceptable.
Library code
And that 'cognizant of the design of the program' clause applies to code in libraries, too. It is very seldom correct for a general purpose library function to call exit(). You'd be justifiably upset if one of the standard C library functions failed to return just because of an error. (Obviously, functions like exit(), _Exit(), quick_exit(), abort() are intended not to return; that's different.) The functions in the C library therefore either "can't fail" or return an error indication somehow. If you're writing code to go into a general purpose library, you need to consider the error handling strategy for your code carefully. It should fit in with the error handling strategies of the programs with which it is intended to be used, or the error handling may be made configurable.
I have a series of library functions (in a package with header "stderr.h", a name which treads on thin ice) that are intended to exit as they're used for error reporting. Those functions exit by design. There are a related series of functions in the same package that report errors and do not exit. The exiting functions are implemented in terms of the non-exiting functions, of course, but that's an internal implementation detail.
I have many other library functions, and a good many of them rely on the "stderr.h" code for error reporting. That's a design decision I made and is one that I'm OK with. But when the errors are reported with the functions that exit, it limits the general usefulness the library code. If the code calls the error reporting functions that do not exit, then the main code paths in the function have to deal with error returns sanely — detect them and relay an error indication to the calling code.
The code for my error reporting package is available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c and stderr.h in the src/libsoq sub-directory.
One reason to avoid exit in functions other than main() is the possibility that your code might be taken out of context. Remember, exit is a type of non local control flow. Like uncatchable exceptions.
For example, you might write some storage management functions that exit on a critical disk error. Then someone decides to move them into a library. Exiting from a library is something that will cause the calling program to exit in an inconsitent state which it may not be prepared for.
Or you might run it on an embedded system. There is nowhere to exit to, the whole thing runs in a while(1) loop in main(). It might not even be defined in the standard library.
Depending on what you are doing, exit may be the most logical way out of a program in C. I know it's very useful for checking to make sure chains of callbacks work correctly. Take this example callback I used recently:
unsigned char cbShowDataThenExit( unsigned char *data, unsigned short dataSz,unsigned char status)
{
printf("cbShowDataThenExit with status %X (dataSz %d)\n", status, dataSz);
printf("status:%d\n",status);
printArray(data,dataSz);
cleanUp();
exit(0);
}
In the main loop, I set everything up for this system and then wait in a while(1) loop. It is possible to make a global flag to exit the while loop instead, but this is simple and does what it needs to do. If you are dealing with any open buffers like files and devices you should clean them up before close for consistency.
It is terrible in a big project when any code can exit except for coredump. Trace is very import to maintain a online server.
Lua docs say:
The Lua library defines no global variables at all. It keeps all its state in the dynamic structure lua_State and a pointer to this
structure is passed as an argument to all functions inside Lua. This
implementation makes Lua reentrant and ready to be used in
multithreaded code.
But is it true? Has anyone tried to verify this? What if a signal is raised and caught by a custom handler during the execution of lua? That is, is lua itself (never mind the system calls it makes) truly reentrant?
EDIT:
A well-known problem in lua is the lack of a timer implementation. These can be implemented using POSIX timers, that raise a signal. But raising such a signal may interrupt the execution of lua itself. The canonical solution to solve this problem is the masking/unmasking of a signal, but if lua were truly re-entrant this would not be needed.
AFAICT, re-entrancy is a single threaded concept, and somewhat independent from multi-threading. Multi-thread safety relates to data coherence when concurrent read/write shared data, whereas re-entrancy relates to state coherence of function pre/post signal, within one thread.
A function is either multi-thread safe, or it is not. There is no in-between. However, it is not so simple with regards to re-entrancy: there are conditions under which a function is re-entrant, and conditions under which it is not; for some functions, there are no conditions under which it is re-entrant. I'm not a computer scientist but my guess is that there are very few functions, if any, that would be re-entrant under all conditions. Like void f() {} would be one, but it's not very useful :)
The following are probably true:
A required condition for a function to be re-entrant is that it must not use any static or global data or data that can be set from outside itself (such as registers or DMA).
Another required condition for re-entrancy is that the function only call re-entrant functions. In this case the function is re-entrant with the sum of all conditions required for the called functions to be considered re-entrant. So if A calls B and C, and B is re-entrant if condition b is true, and C is re-entrant if condition c is true, then a necessary condition for A to be re-entrant is conditions b and c must be true.
A function that accepts at least one argument is only re-entrant if 1 and 2 are true and the signal handler does not call, directly or indirectly, the function with the same argument.
An API is re-entrant in the same manner as the totality of its functions. This means that there may be only a subset of the API that can be said to be re-entrant, under certain specific conditions (1-3), and other functions are not re-entrant. This does not mean the API is not re-entrant; just that a subset of it is re-entrant, under certain conditions.
If the above is correct, then you have to be more specific when asking (or stating) whether Lua is re-entrant, to ask which subset of Lua functions are known to be re-entrant, under what conditions. Apparently all Lua functions satisfy 1, but which ones satisfy 2? Almost all Lua API functions accept at least one argument, so under the condition that your signal handler does not call directly or indirectly the same Lua function with the same Lua state variable, you could say that Lua is re-entrant for those functions that don't call non-reentrant functions.
Update 1: why condition 3:
Consider
void f(const Foo& foo) {
if (foo.bar)
do stuff
signal happens here, calling isr()
modify fo
}
Foo* isrFoo;
void g() {
Foo foo;
isrFoo = & foo;
f(foo)
}
void isr() {
f(*isrFoo)
}
Although f(const Foo&) does not use globals or static (although strictly speaking it doesn't know if a is a ref to such var), the object received can be shared by multiple objects and hence, in isr(), can be modified, such that when f() resumes, foo is no longer same as when interrupted. One could say that f() is re-entrant (in single-thread) but here isr() is interfering, making f() non-re-entrant in that particular case. Assuming that an object copy op could be made atomic, f() could be made re-entrant even for this particular design of isr() if foo was copied into a local variable of f before being used, or if isr() made a local copy, or foo was pass-by-value.
Update 2: russian roulette
Russian roulette is a game of chance. So no, re-entrancy is not game of chance: given the above, the manual says basically that if your signal handler does not call (directly or indirectly) Lua C API functions, then you can consider the Lua C API functions re-entrant because of the way the API was designed and implemented.
For example if you have a timer that ticks (signals) every 100 ms, but the handler just sets a flag to true for "do something ASAP", and your code loops endlessly, calling a Lua function (via lua_pcall) at every iteration, to check the flag, you shouldn't have any problems: if the Lua function is interrupted by the timer before the flag is checked, the flag will get set, then upon return from signal the flag will be seen as true and your function will take action as designed.
However, if you are not careful, your Lua function (not the C API that calls it) may not be re-entrant, thus causing lua_pcall to not be re-entrant when calling your Lua function. For example if your Lua function (called via lua_pcall) checks the flag in two places:
function checkTimerFlagSet()
if flag then ... end
... do stuff ...
if flag then ... end
and the timer signal occurs between the two checks, then the flag could be seen as false before signal and true after, during the same function call, which could lead to inconsistent behavior of your Lua function. But this is merely rule #1 not being followed (no choice since your signal handler can only set global variable) by your function, not by the Lua C API: this "bad" (i.e. non-reentrant) design of your Lua function is what caused one of the Lua C API functions (lua_pcall) to no-longer be re-entrant. It is re-entrant otherwise.
It is true that lua keeps all its variables in lua_State. If a signal occurs, that signal will be handled in C. You cannot call lua safely from your signal handler, just as you can't call even some thread safe functions from a signal handler.
What the documentation is saying is that if you have different threads with different lua_State variables, they can each safely run lua without the need to synchronise between them.