Por que o strace e o ltrace fazem com que o EINTR ocorra?

3

Considere este programa:

#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;
}

Quando eu executo este programa por si só, redimensionar o terminal (gerando assim o SIGWINCH) não faz nada a ele, e ele continua esperando pela entrada no stdin. Quando eu o executo dentro de strace ou ltrace, o SIGWINCH resulta em epoll_wait com erro no EINTR. Meu entendimento do EINTR é que ele é gerado apenas se um sinal chamar um manipulador de sinal em seu código, mas eu não tenho nenhum deles registrado. Eu pensei que strace ou ltrace pode ter sido um cenário para mim, então eu tentei defini-lo explicitamente para SIG_IGN, mas isso ainda não impediu o EINTR. Por que isso está acontecendo?

    
por Joseph Sible 28.08.2018 / 00:14

1 resposta

3

Eles usam ptrace(2) , cuja página de manual comenta

While being traced, the tracee will stop each time a signal is delivered, even if the signal is being ignored. (An exception is SIGKILL, which has its usual effect.) The tracer will be notified at its next call to waitpid(2) (or one of the related "wait" system calls); that call will return a status value containing information that indicates the cause of the stop in the tracee. While the tracee is stopped, the tracer can use various ptrace requests to inspect and modify the tracee. The tracer then causes the tracee to continue, optionally ignoring the delivered signal (or even delivering a different signal instead).

e mais tarde:

Note that a suppressed signal still causes system calls to return prematurely. In this case, system calls will be restarted: the tracer will observe the tracee to reexecute the interrupted system call (or restart_syscall(2) system call for a few system calls which use a different mechanism for restarting) if the tracer uses PTRACE_SYSCALL. Even system calls (such as poll(2)) which are not restartable after signal are restarted after signal is suppressed; however, kernel bugs exist which cause some system calls to fail with EINTR even though no observable signal is injected to the tracee.

Por padrão, SIGWINCH é ignorado, mas parece que epoll é semelhante o suficiente para poll que o EINTR é visível para o chamador (mesmo com a reinicialização) .

    
por 28.08.2018 / 00:58