title: How epoll detect clientside close in Python?
body: <p><strong>Here is my server</strong></p>
  
  <pre><code>"""Server using epoll method"""
  
  import os
  import select
  import socket
  import time
  
  from oodict import OODict
  
  addr = ('localhost', 8989)
  
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  s.bind(addr)
  s.listen(8)
  s.setblocking(0) # Non blocking socket server
  epoll = select.epoll()
  epoll.register(s.fileno(), select.EPOLLIN) # Level triggerred
  
  cs = {}
  data = ''
  while True:
      time.sleep(1)
      events = epoll.poll(1) # Timeout 1 second
      print 'Polling %d events' % len(events)
      for fileno, event in events:
          if fileno == s.fileno():
              sk, addr = s.accept()
              sk.setblocking(0)
              print addr
              cs[sk.fileno()] = sk
              epoll.register(sk.fileno(), select.EPOLLIN)
  
          elif event &amp; select.EPOLLIN:
              data = cs[fileno].recv(4)
              print 'recv ', data
              epoll.modify(fileno, select.EPOLLOUT)
          elif event &amp; select.EPOLLOUT:
              print 'send ', data
              cs[fileno].send(data)
              data = ''
              epoll.modify(fileno, select.EPOLLIN)
  
          elif event &amp; select.EPOLLERR:
              print 'err'
              epoll.unregister(fileno)
  </code></pre>
  
  <p><strong>client side input</strong></p>
  
  <pre><code>ideer@ideer:/home/chenz/source/ideerfs$ telnet localhost 8989
  Trying ::1...
  Trying 127.0.0.1...
  Connected to localhost.
  Escape character is '^]'.
  123456
  123456
  ^]
  
  telnet&gt; q
  Connection closed.
  </code></pre>
  
  <p><strong>server side output</strong></p>
  
  <pre><code>ideer@ideer:/chenz/source/ideerfs$ python epoll.py 
  Polling 0 events
  Polling 0 events
  Polling 1 events
  ('127.0.0.1', 53975)
  Polling 0 events
  Polling 1 events
  recv  1234
  Polling 1 events
  send  1234
  Polling 1 events
  recv  56
  
  Polling 1 events
  send  56
  
  Polling 0 events
  Polling 0 events
  Polling 0 events
  Polling 1 events
  recv  
  Polling 1 events
  send  
  Polling 1 events
  recv  
  Polling 1 events
  send  
  Polling 1 events
  recv  
  Polling 1 events
  send  
  Polling 1 events
  recv  
  ^CTraceback (most recent call last):
    File "epoll.py", line 23, in &lt;module&gt;
      time.sleep(1)
  KeyboardInterrupt
  </code></pre>
  
  <p>It's strange that after the client has closed the connection, epoll still can poll recv and send events! Why does EPOLLERR event never happen? it's the same if you use EPOLLHUP.</p>
  
  <p>I notice that the EPOLLERR event only happens when you try to write a closed connection. 
  Besides this, is there another way to tell that whether the connection has been closed or not?</p>
  
  <p>Is it correct to treat the connection as closed if you get nothing in a EPOLLIN event?</p>