title: epoll loops on disconnection of a client
body: <p>I am trying to implement a socket server by using <code>epoll</code>. I have 2 threads doing 2 tasks:</p>
  
  <ol>
  <li>listening to incoming connection</li>
  <li>writing on screen the data the client is sending.</li>
  </ol>
  
  <p>For my test I have the client and the server on the same machine with 3 or 4 clients running.
  The server works fine until I don't kill one of the client by issuing a <code>CTRL-C</code>: as soon I do that the server starts looping and printing at a very fast rate data from other client. The strange thing is that</p>
  
  <ol>
  <li>the client sends data each 2 seconds but the rate of the server is higher</li>
  <li><code>epoll_wait</code> is also supposed to print something when one of the client disconnects as it is checking also for EPOLLHUP or EPOLLERR</li>
  <li><code>epoll_wait</code> should wait a bit before printing since I gave him a timeout of 3000 milliseconds.</li>
  </ol>
  
  <p>Can you help? Could it be that I am passing in a wrong way the epoll descriptor to the other thread? I cannot understand since the code looks similar to many examples around.</p>
  
  <p>Thanks a lot</p>
  
  <p>Mn</p>
  
  <pre><code> // server.cpp
   #include &lt;iostream&gt;
   #include &lt;cstdio&gt;
   #include &lt;cstring&gt;
   extern "C" {
   #include &lt;sys/epoll.h&gt;    
   #include &lt;sys/socket.h&gt;
   #include &lt;sys/types.h&gt;
   #include &lt;netdb.h&gt;
   #include &lt;pthread.h&gt;
   }
  
   #define MAX_BACKLOG 10
  
   void* readerthread(void* args){
       int epfd = *((int*)args);
       epoll_event outwait[10];
       while(true){
           int retpw = epoll_wait( epfd, outwait,20, 3000 );
           if( retpw == -1 ){
           printf("epoll error %m\n");
           }else if( retpw == 0 ){
           printf("nothing is ready yet\n");
           continue;
           }else{
               for( int i=0;i&lt;retpw;i++){
                   if( outwait[i].events &amp; EPOLLIN ){
                       int fd = outwait[i].data.fd;   
                       char buf[64];
                       if( -1 == read(fd,buf,64) ){
                           printf("error reading %m\n");
                       }
                       printf("%s\n",buf);
                   }else{
                       std::cout &lt;&lt; "other event" &lt;&lt; std::endl;
                   }                  
               }
           }
       }  
   }
  
   int main(){ 
  
        int epfd = epoll_create(10);
        if( -1 == epfd ){
        std::cerr &lt;&lt; "error creating EPOLL server" &lt;&lt; std::endl;
        return -1;
        }
  
        pthread_t reader;
        int rt = pthread_create( &amp;reader, NULL, readerthread, (void*)&amp;epfd );
        if( -1 == rt ){
        printf("thread creation %m\n");
        return -1;
        }
  
  
  
        struct addrinfo addr;
        memset(&amp;addr,0,sizeof(addrinfo));
        addr.ai_family   = AF_INET;
        addr.ai_socktype = SOCK_STREAM;
        addr.ai_protocol = 0;
        addr.ai_flags    = AI_PASSIVE;
  
        struct addrinfo * rp,* result;
        getaddrinfo( "localhost","59000",&amp;addr,&amp;result );
        for( rp = result; rp != NULL; rp = rp-&gt;ai_next ){
  
        // we want to take the first ( it could be IP_V4 
        // or IP_V6 )
        break;
        }     
  
        int sd = socket( AF_INET, SOCK_STREAM, 0 );
        if(-1==sd ){
        std::cerr &lt;&lt; "error creating the socket" &lt;&lt; std::endl;
        return -1;        
        }
        // to avoid error 'Address already in Use'
        int optval = 1;
        setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &amp;optval, sizeof(optval));         
  
        if( -1==bind( sd, result-&gt;ai_addr, result-&gt;ai_addrlen ) ){
        printf("%m\n");
        std::cerr &lt;&lt; "error binding" &lt;&lt; std::endl;
        return -1;
        }
  
        while(true){
  
             std::cout &lt;&lt; "listen" &lt;&lt; std::endl;
             if( -1== listen(sd, MAX_BACKLOG ) ){
                 std::cerr &lt;&lt; "listen didn't work" &lt;&lt; std::endl;
                 return -1;
             }
  
             std::cout &lt;&lt; "accept" &lt;&lt; std::endl;
             sockaddr peer;
                socklen_t addr_size; 
             int pfd = accept( sd, &amp;peer ,&amp;addr_size );
             if( pfd == -1 ){
                 std::cerr &lt;&lt; "error calling accept()" &lt;&lt; std::endl;
                 return -1;
             }
             epoll_event ev;
             ev.data.fd = pfd;
             ev.events =  EPOLLIN;
             std::cout &lt;&lt; "adding to epoll list" &lt;&lt; std::endl;
             if( -1 == epoll_ctl( epfd, EPOLL_CTL_ADD, pfd, &amp;ev ) ){
                 printf("epoll_ctl error %m\n");
                 return -1;
             }
  
        }
  
   }
   // end of server.cpp
  
  
  
   // client.cpp
       #include &lt;iostream&gt;
   #include &lt;cstring&gt;
   #include &lt;cstdio&gt;
   extern "C"{
   #include &lt;sys/socket.h&gt;
   #include &lt;sys/types.h&gt;
   #include &lt;netdb.h&gt;
   }
  
   int main(){
  
        const char* servername = "localhost";
        const char* serverport = "59000";
  
        struct addrinfo server_address;
        memset( &amp;server_address, 0, sizeof(struct addrinfo) );
        server_address.ai_family  =  AF_INET;
        server_address.ai_socktype =  SOCK_STREAM;
        server_address.ai_protocol  =  0; // any protocol
        server_address.ai_flags    =  0;
  
        struct addrinfo * result, * rp;
  
        int res = getaddrinfo( servername, serverport, &amp;server_address, &amp;result );
        if( -1 == res ){
           std::cout &lt;&lt; "I cannot getaddress " &lt;&lt; servername &lt;&lt; std::endl;
           return -1;
        }
  
        int fd = socket( server_address.ai_family
                  , server_address.ai_socktype
                  , server_address.ai_protocol );
        if( -1 == fd ){
        printf("I cannot open a socket %m\n");
              return -1;
        } 
  
       for( rp = result; rp != NULL; rp = rp-&gt;ai_next ){
           std::cout &lt;&lt; "************" &lt;&lt; std::endl;
          if( -1 == connect( fd, rp-&gt;ai_addr, rp-&gt;ai_addrlen ) ){
               close(fd);
           }else{
           std::cout &lt;&lt; "connected" &lt;&lt; std::endl;
           break;
         }
       }
       if( rp == NULL ){
           std::cerr &lt;&lt; "I couldn't connect server " &lt;&lt; servername &lt;&lt; std::endl;
       }
       while(true){
           sleep(2);
           pid_t me = getpid();
           char buf[64];
           bzero( buf,sizeof(buf));
           sprintf( buf,"%ld",me );
           write(fd,buf,sizeof(buf));
           printf("%s\n",buf);
        }
   }
   // end of client.cpp
  </code></pre>