Main Content

Shared data access within signal handler

Access or modification of shared data causes inconsistent state

Description

This defect occurs when you access or modify a shared object inside a signal handler.

Risk

When you define a signal handler function to access or modify a shared object, the handler accesses or modifies the shared object when it receives a signal. If another function is already accessing the shared object, that function causes a race condition and can leave the data in an inconsistent state.

Fix

To access or modify shared objects inside a signal handler, check that the objects are lock-free atomic, or, if they are integers, declare them as volatile sig_atomic_t.

Examples

expand all

#include <signal.h>
#include <stdlib.h>
#include <string.h>

/* declare global variable. */
int e_flag;

void sig_handler(int signum)
{
	/* Signal handler accesses variable that is not
	of type volatile sig_atomic_t. */
    e_flag = signum; 
}

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

In this example, sig_handler accesses e_flag, a variable of type int. A concurrent access by another function can leave e_flag in an inconsistent state.

Correction — Declare Variable of Type volatile sig_atomic_t

Before you access a shared variable from a signal handler, declare the variable with type volatile sig_atomic_t instead of int. You can safely access variables of this type asynchronously.

#include <signal.h>
#include <stdlib.h>
#include <string.h>

/* Declare variable of type volatile sig_atomic_t. */
volatile sig_atomic_t e_flag;
void sig_handler(int signum)
{
	/* Use variable of proper type inside signal handler. */
    e_flag = signum;
    
}

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

Result Information

Group: Programming
Language: C | C++
Default: On for handwritten code, off for generated code
Command-Line Syntax: SIG_HANDLER_SHARED_OBJECT
Impact: Medium

Version History

Introduced in R2017b