title: Why does the read() block in this case?(linux epoll)
body: <p>I am new to <code>unix programming</code> and today I am trying <code>epoll</code> but getting stuck in a problem.</p>
  
  <p>Under <code>level-triggered</code> mode, I think each new input event including <code>Ctrl-D</code> will cause <code>epoll_wait</code> to return. It works fine. But when I type somethings like <code>aaa</code>, follow with <code>Ctrl-D</code>, <code>read</code> blocks. When I type <code>Ctrl-D</code>, it doesn't.</p>
  
  <p>Could you please explain what happens?</p>
  
  <p>And should I read off all data when <code>epoll_wait</code> is done and according <code>fd</code> is ready？</p>
  
  <p>Thanks!</p>
  
  <pre><code>#include &lt;sys/epoll.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;fcntl.h&gt;
  
  int main(int argc, const char *argv[]) {
      // create event
      struct epoll_event stdin_ev, events[10];
  
      // set event
      stdin_ev.events = EPOLLIN;
      stdin_ev.data.fd = STDIN_FILENO;
  
      // create epoll
      int epfd = epoll_create(1), i, rcnt;
      char c;
  
      // set monitoring STDIN_FILENO 
      epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &amp;stdin_ev);
  
      while(1) {
          int ret = epoll_wait(epfd, events, 1, 1000);
  
          // timeout or failed
          if(ret == 0) {
              fprintf(stdout, "timeout\n");
              continue;
          } else if (ret &lt; 0) {
              perror("ret&lt;0");
              exit(EXIT_FAILURE);
          }
  
          // readable
          fprintf(stdout, "%d event(s) happened...\n", ret);
          for(i=0; i &lt; ret; i++) {
              if(events[i].data.fd == STDIN_FILENO &amp;&amp;\
                 events[i].events&amp;EPOLLIN) {
                  // read a char
                  rcnt = read(STDIN_FILENO, &amp;c, 1); 
                  // if read 0 char, EOF?
                  if(rcnt != 1) {
                      fprintf(stdout, "read %d byte\n", rcnt);
                      continue;
                  }
                  // else print ascii
                  fprintf(stdout, "ascii code: %d\n", c);
              }
          } 
      }
      close(epfd);
      return 0;
  }
  </code></pre>
  
  <p>input: <code>aaa</code>+<code>Ctrl-D</code>, result:</p>
  
  <pre><code>timeout
  aaa // &lt;-- `aaa`+`Ctrl-D`
  1 event(s) happened...
  ascii code: 97
  1 event(s) happened...
  ascii code: 97
  1 event(s) happened...
  ascii code: 97
  1 event(s) happened...
  ^C // &lt;-- read block here, `Ctrl-C` to kill
  </code></pre>
  
  <p>Then I try setting <code>STDIN_FILENO</code> to be nonblocking and I find that <code>epoll_wait</code> still tells there is a readable event although <code>read()</code> returns -1. But if I just type <code>Ctrl-D</code>, <code>read()</code> return 0.</p>
  
  <pre><code>#include &lt;sys/epoll.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;fcntl.h&gt;
  
  int set_nonblock(int sfd) {
      int flags, s;
      flags = fcntl(sfd, F_GETFL, 0);
      if(flags == -1) {
          perror("fcntl");
          return -1;
      }
      flags |= O_NONBLOCK;
      s = fcntl(sfd, F_SETFL, flags);
      if(s == -1) {
          perror("fcntl");
          return -1;
      }
      return 0;
  }
  
  int main(int argc, const char *argv[]) {
      // create event
      struct epoll_event stdin_ev, events[10];
  
      // set event
      stdin_ev.events = EPOLLIN;
      stdin_ev.data.fd = STDIN_FILENO;
  
      // create epoll
      int epfd = epoll_create(1), i, rcnt;
      char c;
  
      // set nonblocking
      if(set_nonblock(STDIN_FILENO) != 0) {
          exit(EXIT_FAILURE);
      };
  
      // set monitoring STDIN_FILENO 
      epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &amp;stdin_ev);
  
      while(1) {
          int ret = epoll_wait(epfd, events, 1, 1000);
  
          // timeout or failed
          if(ret == 0) {
              fprintf(stdout, "timeout\n");
              continue;
          } else if (ret &lt; 0) {
              perror("ret&lt;0");
              exit(EXIT_FAILURE);
          }
  
          // readable
          fprintf(stdout, "%d event(s) happened...\n", ret);
          for(i=0;i &lt; ret;i++) {
              if(events[i].data.fd == STDIN_FILENO &amp;&amp;\
                 events[i].events&amp;EPOLLIN) {
                  // read a char
                  rcnt = read(STDIN_FILENO, &amp;c, 1); 
                  // if read 0 char, EOF?
                  if(rcnt != 1) {
                      fprintf(stdout, "read %d byte\n", rcnt);
                      continue;
                  }
                  // else print ascii
                  fprintf(stdout, "ascii code: %d\n", c);
              }
          } 
      }
      close(epfd);
      return 0;
  }
  </code></pre>
  
  <p>result:</p>
  
  <pre><code>timeout
  1 event(s) happened... // &lt;-- `Ctrl-D`
  read 0 byte // &lt;-- read() -&gt; 0
  timeout
  timeout
  aaa // `aaa`+`Ctrl-D`
  1 event(s) happened...
  ascii code: 97
  1 event(s) happened...
  ascii code: 97
  1 event(s) happened...
  ascii code: 97
  read -1 byte // `EPOLLIN` still happens.
  timeout
  ^C
  </code></pre>