ПроблемаНеправильное использование errno в обработчике сигнала происходит, когда вы вызываете одну из следующих функций в обработчике сигнала:
signal
: Вы вызываете signal
функция в обработчике сигналов и затем считывание значения errno
.
Например, функция обработчика сигналов handler
вызывает signal
а затем вызывает perror
, который читается errno
.
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
перед возвращением.
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: An 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;
}