
Рассмотрим эту программу:
#include <stdio.h>
#include <sys/epoll.h>
int main(void) {
int epfd = epoll_create1(0);
struct epoll_event event;
event.events = EPOLLIN;
event.data.fd = 0;
epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event);
epoll_wait(epfd, &event, 1, -1);
perror("epoll_wait");
return 0;
}
Когда я запускаю эту программу отдельно, изменение размера терминала (тем самым генерируя SIGWINCH) ничего не делает с ней, и она продолжает ждать ввода на stdin. Когда я запускаю ее внутри strace или ltrace, SIGWINCH приводит к ошибке epoll_wait с EINTR. Я понимаю EINTR так, что он генерируется только в том случае, если сигнал вызывает обработчик сигнала в вашем коде, но у меня ни один из них не зарегистрирован. Я думал, что strace или ltrace могли установить его для меня, поэтому я попробовал явно установить его в SIG_IGN, но это все равно не остановило EINTR. Почему это происходит?
решение1
Они используютptrace(2)
, чьи комментарии к странице руководства
Во время отслеживания трассируемый объект будет останавливаться каждый раз при получении сигнала,даже если сигнал игнорируется. (Исключением является
SIGKILL
, что имеет свой обычный эффект.) Трейсер будет уведомлен при следующем вызовеwaitpid(2)
(или один из связанных системных вызовов "wait"); этот вызов вернет значение статуса, содержащее информацию, указывающую причину остановки трассируемой. Пока трассируемая линия остановлена, трассировщик может использовать различные запросы ptrace для проверки и изменения трассируемой линии. Затем трассировщик заставляет трассируемую линию продолжить работу, опционально игнорируя доставленный сигнал (или даже доставляя вместо этого другой сигнал).
и позже:
Обратите внимание, что подавленный сигнал все еще приводит к преждевременному возврату системных вызовов. В этом случае системные вызовы будут перезапущены: трассировщик будет наблюдать, как трассируемый повторно выполняет прерванный системный вызов (или
restart_syscall(2)
системный вызов для нескольких системных вызовов, которые используют другой механизм для перезапуска), если трассировщик используетPTRACE_SYSCALL
. Даже системные вызовы (такие какpoll(2)
) которые не подлежат перезапуску после сигнала, перезапускаются после подавления сигнала;Однако существуют ошибки ядра, которые приводят к сбою некоторых системных вызовов с EINTR, даже если в трассируемую цепочку не вводится наблюдаемый сигнал..
По умолчанию,SIGWINCH
игнорируется, но звучит достаточно epoll
похоже, poll
чтобы быть EINTR
видимым для вызывающего абонента (даже после перезапуска).