title: epoll events do not raise SIGIO
body: <p>Based on my research, you can add an epoll file descriptor to poll, select, or another epoll and it will return POLLIN if events are available. According to epoll(7): </p>
  
  <pre><code>   Q3  Is the epoll file descriptor itself poll/epoll/selectable?
  
     A3  Yes.  If an epoll file descriptor has events waiting, then it  will
         indicate as being readable.
  </code></pre>
  
  <p>This works in my testing. But, I am now trying to apply O_ASYNC to my epoll fd so that it will raise SIGIO when events are ready:</p>
  
  <pre><code>//Epoll setup code - trySc runs perror on the string and exits if the function returns -1
  int epollFd = epoll_create1(EPOLL_CLOEXEC);
  trySc(epollFd, "epoll_create1");
  trySc(fcntl(epollFd, F_SETOWN, getpid()), "fcntl F_SETOWN");
  trySc(fcntl(epollFd, F_SETSIG, SIGIO), "fcntl F_SETSIG");
  int oldFlags = fcntl(epollFd, F_GETFL, 0);
  trySc(oldFlags, "fcntl F_GETFL");
  trySc(fcntl(epollFd, F_SETFL, oldFlags | O_ASYNC), "fcntl F_SETFL");
  
  //Set up SIGIO and get a socket fd, you don't need to see this
  //All my handler does is exit - it's a definite method of knowing SIGIO was raised
  
  struct epoll_event event = {
          .events = EPOLLIN | EPOLLET,
          .data.fd = socketFd
  };
  trySc(epoll_ctl(epollFd, EPOLL_CTL_ADD, socketFd, &amp;event), "epoll_ctl");
  //Then connect
  while(1){
          struct pollfd pfd = {
                  .fd = epollFd,
                  .events = POLLIN
          };
          //This blocks until I write something to the socket. Then it enters an infinite loop.
          printf("Returning to main(), poll = %d\n", poll(&amp;pfd, 1, -1));
  }
  </code></pre>
  
  <p>When I do this, it doesn't raise SIGIO for the new events in epoll. Poll indicates that there are events ready in epollFd, but it should raise SIGIO (which just checks to see if events are in epollFd and exits) first. I know I can apply O_ASYNC to the socket (and I have tried this too) but I wish to include data with my events. Epoll lets me do this.</p>
  
  <p>Here is my full code:</p>
  
  <pre><code>#define _GNU_SOURCE
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;sys/epoll.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;poll.h&gt;
  #include &lt;signal.h&gt;
  #include &lt;errno.h&gt;
  
  void handleSIGIO(int, siginfo_t *, void *);
  
  const struct sigaction saSIGIO = {
      .sa_sigaction = handleSIGIO,
      .sa_flags = SA_SIGINFO
  };
  
  const struct addrinfo hints = {
      .ai_flags = AI_PASSIVE,
      .ai_family = AF_INET,
      .ai_socktype = SOCK_STREAM
  };
  
  void trySc(int err, const char *msg){
      if(err != -1) return;
      perror(msg);
      exit(errno);
  }
  
  int main(){
      signal(SIGPIPE, SIG_IGN);
      trySc(sigaction(SIGIO, &amp;saSIGIO, NULL), "sigaction");
      int epollFd = epoll_create1(EPOLL_CLOEXEC);
      trySc(epollFd, "epoll_create1");
      trySc(fcntl(epollFd, F_SETOWN, getpid()), "fcntl F_SETOWN");
      trySc(fcntl(epollFd, F_SETSIG, SIGIO), "fcntl F_SETSIG");
      int oldFlags = fcntl(epollFd, F_GETFL, 0);
      trySc(oldFlags, "fcntl F_GETFL");
      trySc(fcntl(epollFd, F_SETFL, oldFlags | O_ASYNC), "fcntl F_SETFL");
      int socketFd = socket(AF_INET, SOCK_STREAM, 0);
      trySc(socketFd, "socket");
      struct addrinfo *servinfo;
      trySc(getaddrinfo("127.0.0.1", "5000", &amp;hints, &amp;servinfo),
          "getaddrinfo");
      struct epoll_event event = {
          .events = EPOLLIN | EPOLLET,
          .data.fd = socketFd
      };
      trySc(epoll_ctl(epollFd, EPOLL_CTL_ADD, socketFd, &amp;event), "epoll_ctl");
      trySc(connect(socketFd, servinfo-&gt;ai_addr, servinfo-&gt;ai_addrlen),
          "connect");
      printf("Connected\n");
      while(1){
          struct pollfd pfd = {
              .fd = epollFd,
              .events = POLLIN
          };
          printf("Returning to main(), poll = %d\n", poll(&amp;pfd, 1, -1));
      }
  }
  
  void handleSIGIO(int sn, siginfo_t *info, void *ctx){
      printf("SIGIO called\n");
      struct epoll_event event;
      if(epoll_wait(info-&gt;si_fd, &amp;event, 1, 0) != 1){
          printf("Warning: no event available\n");
          return;
      }
      printf("Event raised for fd %d\n", event.data.fd);
      exit(0);
  }
  </code></pre>
  
  <p>Edit: According to <a href="http://compgeom.com/~piyush/teach/4531_06/project/hell.html" rel="nofollow noreferrer">this website</a>, what I am trying to do should work:</p>
  
  <pre><code>Note that an epoll set descriptor can be used much like a regular file 
  descriptor. That is, it can be made to generate SIGIO (or another signal)
  when input (i.e. events) is available on it; likewise it can be used with 
  poll() and can even be stored inside another epoll set.
  </code></pre>