ПроблемаНеправильное использование errno в обработчике сигнала происходит при вызове одной из следующих функций в обработчике сигнала:
signal: Вы называете signal функция в обработчике сигнала, а затем считывание значения errno.
Например, функция обработчика сигнала handler требования signal а затем звонит perror, который гласит: errno.
typedef void (*pfv)(int);
void handler(int signum) {
pfv old_handler = signal(signum, SIG_DFL);
if (old_handler == SIG_ERR) {
perror("SIGINT handler");
}
}errno-настройка функции POSIX ®: вы вызываете errno-настройка функции POSIX в обработчике сигналов, но не восстановление errno при возврате от обработчика сигнала.
Например, функция обработчика сигнала handler требования waitpid, который изменяется errno, но не восстанавливает errno перед возвращением.
#include <stddef.h>
#include <errno.h>
#include <sys/wait.h>
void handler(int signum) {
int rc = waitpid(-1, NULL, WNOHANG);
if (ECHILD != errno) {
}
}
РискВ каждом случае, когда средство проверки помечает, вы рискуете полагаться на неопределенное значение errno.
signal: Если вызов signal в обработчике сигнала, значение errno является неопределенным (см. C11 Стандарт, раздел 7.14.1.1). Если вы полагаетесь на определенное значение errno, вы можете увидеть неожиданные результаты.
errno-настройка функции POSIX: errno-настройка наборов функций errno при отказе. Если вы читаете errno после вызова обработчика сигнала, и сам обработчик сигнала вызывает errno-настройка функции, можно увидеть неожиданные результаты.
ЗафиксироватьИзбегайте ситуаций, когда вы рискуете полагаться на неопределенное значение errno.
signal: После вызова signal функция в обработчике сигнала, не считывайте errno или используйте функцию, которая считывает errno.
errno-настройка функции POSIX: перед вызовом errno-настройка функции в обработчике сигналов, сохранение errno к временной переменной. Восстановить errno от этой переменной перед возвратом от обработчика сигнала.
Пример - чтение errno После signal Обработчик сигнала вызова#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#define fatal_error() abort()
void handler(int signum) {
if (signal(signum, SIG_DFL) == SIG_ERR) {
perror("SIGINT handler");
}
}
int func(void) {
if (signal(SIGINT, handler) == SIG_ERR) {
/* Handle error */
fatal_error();
}
/* Program code */
if (raise(SIGINT) != 0) {
/* Handle error */
fatal_error();
}
return 0;
}В этом примере функция handler вызывается для обработки SIGINT сигнал. В теле handler, signal вызывается функция. После этого вызова значение errno является неопределенным. Шашка поднимает дефект, когда perror функция вызывается, поскольку perror полагается на значение errno.
Исправление - избегайте чтения errno После signal ЗвонитьОдно из возможных исправлений - не читать errno после вызова signal функция в обработчике сигнала. Исправленный код вызывает abort через fatal_error макро вместо perror функция.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#define fatal_error() abort()
void handler(int signum) {
if (signal(signum, SIG_DFL) == SIG_ERR) {
fatal_error();
}
}
int func(void) {
if (signal(SIGINT, handler) == SIG_ERR) {
/* Handle error */
fatal_error();
}
/* Program code */
if (raise(SIGINT) != 0) {
/* Handle error */
fatal_error();
}
return 0;
}