다음 프로그램을 고려해보세요:
#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 생성) 아무런 작업도 수행되지 않으며 계속해서 표준 입력에 대한 입력을 기다립니다. strace 또는 ltrace에서 실행할 때 SIGWINCH는 epoll_wait에서 EINTR 오류를 발생시킵니다. EINTR에 대한 나의 이해는 신호가 코드에서 신호 처리기를 호출할 때만 생성되지만 그 중 어떤 것도 등록하지 않는다는 것입니다. 나는 strace나 ltrace가 나를 위해 하나를 설정했을지도 모른다고 생각하여 명시적으로 SIG_IGN으로 설정하려고 시도했지만 여전히 EINTR을 막지는 못했습니다. 왜 이런 일이 발생합니까?
답변1
그들은 사용한다ptrace(2)
, 그의 매뉴얼 페이지가 댓글을 달았습니다.
추적되는 동안, 추적되는 사람은 신호가 주어질 때마다 멈추게 되며,신호를 무시해도. (한 가지 예외는
SIGKILL
, 이는 일반적인 효과를 갖습니다. ) 추적기는 다음에 호출될 때 알림을 받습니다.waitpid(2)
(또는 관련 "대기" 시스템 호출 중 하나) 이 호출은 추적된 사람이 중지된 이유를 나타내는 정보가 포함된 상태 값을 반환합니다. 피추적자가 중지되면 추적기는 다양한 ptrace 요청을 사용하여 피추적자를 검사하고 수정할 수 있습니다. 그런 다음 추적기는 추적이 진행되도록 활성화하고 선택적으로 전달된 신호를 무시합니다(또는 다른 신호 전달도 가능).
그 다음에:
신호를 억제하면 시스템 호출이 조기에 반환될 수 있습니다. 이 경우, 시스템 호출은 다시 시작될 것이다: 추적자는 피추적자가 중단된 시스템 호출을 다시 실행하는 것을 관찰할 것이다(또는
restart_syscall(2)
추적기가 사용하는 경우 시스템 호출(다시 시작하기 위해 다른 메커니즘을 사용하는 일부 시스템 호출의 경우)PTRACE_SYSCALL
. 심지어 시스템 호출(예:poll(2)
) 신호가 억제된 후에는 신호가 다시 시작된 후에 다시 시작할 수 없습니다.그러나 관찰 가능한 신호가 피추적자에 주입되지 않은 경우에도 EINTR과 함께 특정 시스템 호출이 실패할 수 있는 커널 버그가 있습니다..
기본적으로,SIGWINCH
무시되지만 발신자가 볼 수 있을 epoll
만큼 비슷하게 들립니다(재부팅 시에도).poll
EINTR