Описание
Функция, вызванная от обработчика сигнала, не асинхронно-безопасного (строгий), происходит, когда обработчик сигнала вызывает функцию, которая не асинхронно-безопасна согласно стандарту C. Асинхронно-безопасная функция может быть прервана в любой точке в ее выполнении, затем названном снова, не вызывая противоречивое состояние. Это может также правильно обработать глобальные данные, которые могут быть в противоречивом состоянии.
Когда вы выбираете Функцию средства проверки, вызванную из обработчика сигнала, не асинхронно-безопасного, средство проверки обнаруживает вызовы функций, которые не асинхронно-безопасны согласно стандарту POSIX. Функция, вызванная от обработчика сигнала, не асинхронно-безопасного (строгий), не повышает дефект для этих случаев. Функция вызвала от обработчика сигнала не асинхронно-безопасные (строгие) повышения дефект для функций, которые асинхронно-безопасны согласно стандарту POSIX, но не согласно стандарту C.
Если обработчик сигнала вызывает другую функцию, которая вызывает асинхронно-небезопасную функцию, дефект появляется на вызове функции в обработчике сигнала. Дефект traceback показывает полный путь от обработчика сигнала до асинхронно-небезопасной функции.
Риск
Когда обработчик сигнала вызывается, осуществление программы прервано. После того, как обработчик закончен, резюме выполнения программы при прерывании. Если функция выполняется во время прерывания, вызывание его из обработчика сигнала является неопределенным поведением, если это не асинхронно-безопасно.
Фиксация
Стандарт 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;
}