Проблема
Функция, вызываемая от обработчика сигнала, не асинхронно-безопасного (строгого), возникает, когда обработчик сигнала вызывает функцию, которая не асинхронно-безопасна в соответствии со стандартом C. Асинхронно-безопасная функция может быть прервана в любой момент ее выполнения, затем вызвана снова, не вызывая несогласованного состояния. Он также может правильно обрабатывать глобальные данные, которые могут находиться в несогласованном состоянии.
При выборе проверки Function, вызываемой от обработчика сигнала, не асинхронно-безопасного, проверка обнаруживает вызовы функций, которые не являются асинхронно-безопасными в соответствии со стандартом POSIX. Функция, вызываемая от обработчика сигнала, не асинхронно-безопасного (строгого), не вызывает дефект для этих случаев. Функция, вызываемая от обработчика сигнала, не асинхронно-безопасного (строгого), вызывает дефект для функций, которые асинхронно-безопасны в соответствии со стандартом POSIX, но не согласно стандарту C.
Если обработчик сигнала вызывает другую функцию, которая вызывает асинхронно-небезопасную функцию, дефект появляется при вызове функции в обработчике сигнала. Трассировка дефекта показывает полный путь от обработчика сигнала до асинхронно-небезопасной функции.
РискКогда вызывается обработчик сигнала, выполнение программы прерывается. После завершения работы обработчика выполнение программы возобновляется в точке прерывания. Если функция выполняется во время прерывания, вызов ее из обработчика сигнала является неопределенным поведением, если только это не асинхронно-безопасно.
ЗафиксироватьСтандарт C определяет следующие функции как асинхронно-безопасные. Можно вызвать эти функции из обработчика сигнала:
abort()
_Exit()
quick_exit()
signal()
Пример - Вызов к raise() Обработчик внутреннего сигнала#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;
}
В этом примере sig_handler вызывает raise() при захвате сигнала. Если обработчик захватывает другой сигнал во время raise() выполняется, поведение программы не определено.
Коррекция - Удаление вызова для raise() в обработчике сигналовСогласно стандарту C, единственные функции, которые можно безопасно вызвать с обработчика сигнала abort(), _Exit(), quick_exit(), и 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;
}