Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The C99 exit() function is used for normal program termination. Nested calls to exit() result in undefined behavior. This can only occur when exit() is invoked from a function registered with atexit(), or when exit() is called from within a signal handler (see SIG30-C. Call only asynchronous-safe functions within signal handlers).

Additionally, if a call to the longjmp function is made that would terminate the call to a function registered with atexit(), the behavior is undefined.

Consequently, no No atexit() registered handler should terminate in any way other than by returning. It is important and potentially safety-critical for all the atexit() handlers to be allowed to perform their cleanup actions. This is particularly true because the main program does not always know about handlers that may have been installed by support libraries.

...

Code Block
bgColor#ccccFF
#include <stdio.h>
#include <stdlib.h>

void exit1(void) {
  /* ...cleanup code... */
  return;
}

void exit2(void) {
  if (/* condition */) {
    /* ...more cleanup code... */
  }
  return;
}

int main(void) {
  atexit(exit1);
  atexit(exit2);
  /* ...program code... */
  exit(0);
}

Non-Compliant Code Example

The function exit1() is registered by atexit(), so upon program termination, exit1() is called. Execution will jump back to main and return, with undefined results.

Code Block
bgColor#FFcccc

#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

jmp_buf env;
int val;

void exit1(void) {
  /* ... */
  longjmp(env, 1);
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* handle error */
  }
  /* ... */
  if (setjmp(env) == 0) {
    exit(0);
  }
  else {
    return 0;
  }
}

Compliant Code

Careful thought about program flow is the best prevention for an invalid call to longjmp(). After the exit function has been called, avoid using longjmp() where it will cause a function to terminate.

Code Block
bgColor#ccccFF

#include <stdlib.h>

void exit1(void) {
  /* ... */
  return;
}

int main(void) {
  if (atexit(exit1) != 0) {
    /* handle error */
  }
  /* ... */
  exit(0);
}

Risk Assessment

...