Проблема
Функция, вызванная от обработчика сигнала, не асинхронно-безопасного (строгий), происходит, когда обработчик сигнала вызывает функцию, которая не асинхронно-безопасна согласно стандарту 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()
выход
, 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;
}