title: Python asyncio: closing a socket and releasing an await sock_read()
body: <p>I'm writing a small multi-user game.  Users are logged on via console or sockets.  I want to be able to kick out other users.  </p>
  
  <p>I use <code>asyncio</code> and wait for user input by calling <code>await loop.sock_recv(sock, 256)</code>.  Now, if some other user (say, from the console) closes the socket, the event crashes since <code>select.select</code> seems to have problems.</p>
  
  <p>How can I kill a connection and release the <code>sock_recv()</code>?</p>
  
  <p>Attached is a small(ish) MWE.  It creates listening sockets and will accept a connection on port 4000.  After that you can kill a connection by entering <code>"x"</code> on the console.  <code>logoff()</code> is my attempt to kill the connection.</p>
  
  <pre><code>import asyncio
  import socket
  import sys
  import threading
  
  
  # ------ console input -------------------------------------------------------
  
  async def _ainput(loop):
      fut = loop.create_future()
      def _run():
          line = sys.stdin.readline().strip()
          loop.call_soon_threadsafe(fut.set_result, line)
      threading.Thread(target=_run, daemon=True).start()
      return await fut
  
  async def console_input_loop(loop):
      while True:
          inp = (await _ainput(loop)).strip()
          print(f"[{inp.strip()}]")
          if inp == "x":
              logoff()
  
  
  # ------ socket input --------------------------------------------------------
  
  alive = True
  
  async def socket_input_loop(loop, sock):
      print(f"New connection")
  
      global alive
      while alive:
          try:
              inp = await loop.sock_recv(sock, 256)
          except ConnectionResetError:
              break
          print(inp)
  
      print("shutting down")
      sock.shutdown(socket.SHUT_RDWR)
      sock.close()
      print(f"Connection closed")
      alive = True
  
  listen_addr = ('', 4000)
  
  async def _run_server(loop, server):
      server.bind(listen_addr)
      server.listen(8)
      server.setblocking(False)
  
      while loop.is_running():
          global sock
          sock = (await loop.sock_accept(server))[0]
          loop.create_task(socket_input_loop(loop, sock))
  
  async def run_server4(loop):
      await _run_server(loop, socket.socket(socket.AF_INET, socket.SOCK_STREAM))
  
  async def run_server6(loop):
      await _run_server(loop, socket.socket(socket.AF_INET6, socket.SOCK_STREAM))
  
  def async_driver():
      loop = asyncio.get_event_loop()
      loop.create_task(console_input_loop(loop))
      loop.create_task(run_server4(loop))
      loop.create_task(run_server6(loop))
      loop.run_forever()
      print()
  
  def logoff():
      global alive
      alive = False
      #loop = asyncio.get_event_loop()
      #try:
      #    key = loop._selector.get_key(sock.fileno())
      #except KeyError:
      #    pass
      #else:
      #    mask, (reader, writer) = key.events, key.data
      #    #loop._add_callback(reader)
      # the next line is needed, otherwise we get:
      #     r, w, x = select.select(r, w, w, timeout)
      # OSError: [WinError 10038] An operation was attempted on something that is not a socket    
      #loop.remove_reader(sock.fileno())   
      sock.shutdown(socket.SHUT_RDWR)
      sock.close()
      #reader._run()
  
  async_driver()
  </code></pre>
  
  <p>I get this crash:</p>
  
  <pre><code>Traceback (most recent call last):
    File "C:\xx7.py", line 91, in &lt;module&gt;
      async_driver()
    File "C:\xx7.py", line 69, in async_driver
      loop.run_forever()
    File "C:\Users\chris\Anaconda3\lib\asyncio\base_events.py", line 528, in run_forever
      self._run_once()
    File "C:\Users\chris\Anaconda3\lib\asyncio\base_events.py", line 1728, in _run_once
      event_list = self._selector.select(timeout)
    File "C:\Users\chris\Anaconda3\lib\selectors.py", line 323, in select
      r, w, _ = self._select(self._readers, self._writers, [], timeout)
    File "C:\Users\chris\Anaconda3\lib\selectors.py", line 314, in _select
      r, w, x = select.select(r, w, w, timeout)
  OSError: [WinError 10038] An operation was attempted on something that is not a socket
  </code></pre>