0
votes

consider the following case:

  • an EPOLLIN event is registered for fd 0 (stdin)
  • an EPOLLIN event is generated for fd 0 and implicitly queued for read within epoll
  • fd 0 is closed (and EPOLL_CTL_DELeted) before calling epoll_wait()
  • epoll_wait() is called to read the queued events

Now:

  • if stdin is a terminal, when epoll_wait() is called, the EPOLLIN event from step 2 will be reported
  • if stdin is not a terminal but a pipe, the EPOLLIN event from step 2 will not be reported

Why is the tty case different?

The test program:

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

running the program with stdin from tty:

[root@tinkerbell src]# ./epolltest 
false
closing stdin ...
gathering events ...
event received: event=1 on fd 0
[root@tinkerbell src]# false
[root@tinkerbell src]# 

running the program with stdin from a pipe:

[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]# 
1

1 Answers

0
votes

different question but the answer can be applied here as well

Events caught by epoll comes from a file* since that is the abstraction the kernel handles. Events really happen on the file* and there's no way if you dup()ing 1000 times a single fd, to say that events are for fd = 122.