Shared data access within signal handler

Доступ или изменение разделяемых данных вызывают несогласованное состояние

Описание

Этот дефект возникает, когда вы получаете доступ или изменяете общий объект внутри обработчика сигнала.

Риск

Когда вы задаете функцию обработчика сигналов для доступа или изменения общего объекта, обработчик обращается или изменяет общий объект, когда он получает сигнал. Если другая функция уже обращается к общему объекту, эта функция вызывает условие расы и может оставить данные в несогласованном состоянии.

Зафиксировать

Чтобы получить доступ или изменить общие объекты внутри обработчика сигнала, проверяйте, что объекты являются безблокировочными атомарными, или, если они являются целыми числами, объявляйте их как volatile sig_atomic_t.

Примеры

расширить все

#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;
}
        
      

В этом примере sig_handler обращается к e_flag, переменная типа int. Параллельный доступ другой функции может покинуть e_flag в несогласованном состоянии.

Коррекция - Объявление переменной типа volatile sig_atomic_t

Прежде чем вы получите доступ к общей переменной от обработчика сигнала, объявите переменную с типом volatile sig_atomic_t вместо int. Вы можете безопасно получить доступ к переменным этого типа асинхронно.

#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;
} 

Информация о результатах

Группа: Программирование
Язык: C | C++
По умолчанию: On для рукописного кода, off для сгенерированного кода
Синтаксис командной строки : SIG_HANDLER_SHARED_OBJECT
Влияние: Средний
ИДЕНТИФИКАТОР CWE: 364, 413
Введенный в R2017b