Проблема
Доступ к разделяемым данным внутри обработчика сигналов происходит, когда вы получаете доступ или изменяете общий объект внутри обработчика сигналов.
РискКогда вы задаете функцию обработчика сигналов для доступа или изменения общего объекта, обработчик обращается или изменяет общий объект, когда он получает сигнал. Если другая функция уже обращается к общему объекту, эта функция вызывает условие расы и может оставить данные в несогласованном состоянии.
ЗафиксироватьЧтобы получить доступ или изменить общие объекты внутри обработчика сигнала, проверяйте, что объекты являются безблокировочными атомарными, или, если они являются целыми числами, объявляйте их как volatile sig_atomic_t
.
Пример - int
Переменный доступ в обработчике сигналов#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;
}