рассмотрим следующий случай:
- событие EPOLLIN зарегистрировано для fd 0 (stdin)
- событие EPOLLIN генерируется для fd 0 и неявно ставится в очередь для чтения в epoll
- fd 0 закрыт (и EPOLL_CTL_DELeted) перед вызовом epoll_wait()
- epoll_wait() вызывается для чтения событий в очереди
Сейчас:
- если стандартный ввод является терминалом, при вызове epoll_wait() будет сообщено о событии EPOLLIN из шага 2.
- если стандартный ввод является не терминалом, а каналом, событие EPOLLIN из шага 2 не будет сообщено
Почему случай tty отличается?
Программа испытаний:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
struct epoll_event event1 = {
.events = EPOLLIN,
.data = { .fd = 0}
};
int main(int argc, char **argv)
{
int epfd = epoll_create(1);
int rc;
epoll_ctl(epfd, EPOLL_CTL_ADD, 0, &event1);
sleep(2); //allow meself time to type false\n
printf("closing stdin ...\n");
close(0);
//even if i remove it explicitly the event will be found in the que after
epoll_ctl(epfd, EPOLL_CTL_DEL, 0, &event1);
printf("gathering events ...\n");
event1.events = 0;
event1.data.fd = -1;
rc = epoll_wait(epfd, &event1, 1, 0);
switch(rc) {
case 1:
printf("event received: event=%d on fd %d\n", event1.events, event1.data.fd);
break;
case 0:
printf("no events received");
break;
case -1:
printf("epoll_wait error\n");
break;
default:
printf("weird event count %d\n", rc);
}
return 0;
}
запуск программы с помощью stdin из tty:
[root@tinkerbell src]# ./epolltest
false
closing stdin ...
gathering events ...
event received: event=1 on fd 0
[root@tinkerbell src]# false
[root@tinkerbell src]#
запуск программы с помощью стандартного ввода из канала:
[root@tinkerbell src]# cat t.sh
#!/bin/bash
echo "bah";
sleep 10;
[root@tinkerbell src]# ./t.sh | ./epolltest
closing stdin ...
gathering events ...
no events received[root@tinkerbell src]#