Main Content

Abnormal termination of exit handler

Exit handler function interrupts the normal execution of a program

Description

This defect occurs when an exit handler itself calls another function that interrupts the program’s expected termination sequence and causes an abnormal exit.

  • Exit handlers are functions designated for execution when a program terminates. These functions are first registered with specific functions such as atexit, (WinAPI) _onexit, or at_quick_exit().

  • Some functions that can cause abnormal exits are exit, abort, longjmp, or (WinAPI) _onexit.

Risk

If your exit handler terminates your program, you can have undefined behavior. Abnormal program termination means other exit handlers are not invoked. These additional exit handlers may do additional clean up or other required termination steps.

Fix

In inside exit handlers, remove calls to functions that prevent the exit handler from terminating normally.

Examples

expand all

#include <stdlib.h>

volatile int some_condition = 1;
void demo_exit1(void)
{
    /* ... Cleanup code ... */
    return;
}
void exitabnormalhandler(void)
{
    if (some_condition)
    {
        /* Clean up */
        exit(0);
    }
    return;
}

int demo_install_exitabnormalhandler(void)
{

    if (atexit(demo_exit1) != 0) /* demo_exit1() performs additional cleanup */
    {
        /* Handle error */
    }
    if (atexit(exitabnormalhandler) != 0)
    {
        /* Handle error */
    }
    /* ... Program code ... */
    return 0;
}

In this example, demo_install_exitabnormalhandler registers two exit handlers, demo_exit1 and exitabnormalhandler. Exit handlers are invoked in the reverse order of which they are registered. When the program ends, exitabnormalhandler runs, then demo_exit1. However, exitabnormalhandler calls exit interrupting the program exit process. Having this exit inside an exit handler causes undefined behavior because the program is not finished cleaning up safely.

Correction — Remove exit from Exit Handler

One possible correction is to let your exit handlers terminate normally. For this example, exit is removed from exitabnormalhandler, allowing the exit termination process to complete as expected.

#include <stdlib.h>

volatile int some_condition = 1;
void demo_exit1(void)
{
    /* ... Cleanup code ... */
    return;
}
void exitabnormalhandler(void)
{
    if (some_condition)
    {
        /* Clean up */
        /* Return normally */
    }
    return;
}

int demo_install_exitabnormalhandler(void)
{

    if (atexit(demo_exit1) != 0) /* demo_exit1() continues clean up */
    {
        /* Handle error */
    }
    if (atexit(exitabnormalhandler) != 0) 
    {
        /* Handle error */
    }
    /* ... Program code ... */
    return 0;
}

Result Information

Group: Programming
Language: C | C++
Default: Off
Command-Line Syntax: EXIT_ABNORMAL_HANDLER
Impact: Medium

Version History

Introduced in R2016b