Main Content

Function called from signal handler not asynchronous-safe (strict ISO C)

Call to interrupted function causes undefined program behavior

Description

This defect occurs when a signal handler calls a function that is not asynchronous-safe according to the C standard. An asynchronous-safe function can be interrupted at any point in its execution, then called again without causing an inconsistent state. It can also correctly handle global data that might be in an inconsistent state.

The C standard defines a stricter subset of functions as asynchronous-safe compared to the set of functions that are asynchronous-safe according to the POSIX standard. Function called from signal handler not asynchronous-safe (strict ISO C) reports a defect when a signal handler calls any function that is not part of that subset, even if the function is asynchronous-safe according to the POSIX standard.

To check for calls to functions that are not asynchronous-safe according to the POSIX standard, enable checker Function called from signal handler not asynchronous-safe.

If a signal handler calls another function that calls an asynchronous-unsafe function, the defect appears on the function call in the signal handler. The defect traceback shows the full path from the signal handler to the asynchronous-unsafe function.

Risk

When a signal handler is invoked, the execution of the program is interrupted. After the handler is finished, program execution resumes at the point of interruption. If a function is executing at the time of the interruption, calling it from within the signal handler is undefined behavior, unless it is asynchronous-safe.

Fix

The C standard defines the following functions as asynchronous-safe. You can call these functions from a signal handler:

  • abort()

  • _Exit()

  • quick_exit()

  • signal()

Examples

expand all

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <syslog.h>
#include <unistd.h>

void SIG_ERR_handler(int signum)
{
    int s0 = signum;
    /* SIGTERM specific handling */
}

void sig_handler(int signum)
{
    int s0 = signum;
	/* Call raise() */ 
    if (raise(SIGTERM) != 0) { 
        /* Handle error */
    }
}

int finc(void)
{
    if (signal(SIGTERM, SIG_ERR_handler) == SIG_ERR)
    {
        /* Handle error */
    }
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        /* Handle error */
    }
    /* Program code */
    if (raise(SIGINT) != 0)
    {
        /* Handle error */
    }
    /* More code */
    return 0;
}
        
      

In this example, sig_handler calls raise() when catching a signal. If the handler catches another signal while raise() is executing, the behavior of the program is undefined.

Correction — Remove Call to raise() in Signal Handler

According to the C standard, the only functions that you can safely call from a signal handler are abort(), _Exit(), quick_exit(), and signal().

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <syslog.h>
#include <unistd.h>

void SIG_ERR_handler(int signum)
{
    int s0 = signum;
    /* SIGTERM specific handling */
}
void sig_handler(int signum)
{
    int s0 = signum;
	
  
}

int func(void)
{
    if (signal(SIGTERM, SIG_ERR_handler) == SIG_ERR)
    {
        /* Handle error */
    }
    if (signal(SIGINT, sig_handler) == SIG_ERR)
    {
        /* Handle error */
    }
    /* Program code */
    if (raise(SIGINT) != 0)
    {
        /* Handle error */
    }
    /* More code */
    return 0;
} 

Result Information

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

Version History

Introduced in R2017b