The C99 exit()
function is used for normal program termination. If more than one call to exit()
is executed by a program, the behavior is undefined. This may occur when functions are registered with atexit()
, a function that causes the functions registered to it to be called with when the program exits. If a function called as a result of being registered with atexit()
has an exit()
call in it there is undefined behavior.
Non-Compliant Code Example
In this code as the main function exits two functions registered with atexit()
are called. Given the define statement exitearly=1 the program calls exit within the first function called in the atexit() cycle. The behavior that follows is undefined: some implementations will ignore the second call to exit and just continue calling the atexit functions in the appropriate order. Other implementations will enter an infinite loop with the atexit functions being called repeatedly.
#include <stdio.h> #include <stdlib.h> #define exitearly 1 void exit1(void) { puts("Exit second.\n"); } void exit2(void) { puts("Exit first.\n"); if (exitearly) { exit(1); } } int main (void) { if (expr) { atexit(exit1); atexit(exit2); exit(1); } else { exit2(); } return 0; }
Compliant Code
To have functionality where the program can quit from within a function registered by at_exit() it is necessary to use a function used for abnormal termination such as _exit() or abort().
From the man page of _exit():
The function _exit terminates the calling process "immediately". Any open file descriptors belonging to the process are closed; any children of the process are inherited by process 1, init, and the process's parent is sent a SIGCHLD signal.
#include <stdio.h> #include <stdlib.h> #define exitearly 1 void exit1(void) { printf("Exit second.\n"); } void exit2 (void) { printf("Exit first.\n"); if (exitearly) { _exit(1); } } int main (void) { if (expr) { atexit(exit1); atexit(exit2); exit(1); } else { exit2(); } return 0; }
All functions registered by the atexit()
function are called, in the reverse order of their registration.
Risk Assessment
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MSC31-C |
1 (low) |
1 (unlikely) |
3(low) |
P6 |
L2 |
References
[[ISO/IEC 9899-1999]] Section 7.20.4.3, "The exit function"