title: Graceful shutdown of asyncio coroutines
body: <p>I'm currently having problems closing asyncio coroutines during the shutdown CTRL-C of an application. The following code is a stripped down version of what I have right now:</p>
  
  <pre><code>#!/usr/bin/env python
  # -*- coding: UTF-8 -*-
  import asyncio
  import time
  import functools
  import signal
  
  
  class DummyProtocol(asyncio.Protocol):
  
      def __init__(self, *args, **kwargs):
          self._shutdown = asyncio.Event()
          self._response = asyncio.Queue(maxsize=1)
          super().__init__(*args, **kwargs)
  
      def connection_made(self, transport):
          self.transport = transport
  
      def close(self):
          print("Closing protocol")
          self._shutdown.set()
  
      def data_received(self, data):
  
          #data = b'OK MPD '
  
          # Start listening for commands after a successful handshake
          if data.startswith(b'OK MPD '):
              print("Ready for sending commands")
              self._proxy_task = asyncio.ensure_future(self._send_commands())
              return
  
          # saving response for later consumption in self._send_commands
          self._response.put_nowait(data)
  
      async def _send_commands(self):
  
          while not self._shutdown.is_set():
  
              print("Waiting for commands coming in ...")
  
              command = None
  
              # listen for commands coming in from the global command queue. Only blocking 1sec.
              try:
                  command = await asyncio.wait_for(cmd_queue.get(), timeout=1)
              except asyncio.TimeoutError:
                  continue
  
              # sending the command over the pipe
              self.transport.write(command)
  
              # waiting for the response. Blocking until response is complete.
              res = await self._response.get()
              # put it into the global response queue
              res_queue.put_nowait(res)
  
  
  async def connect(loop):
      c = lambda: DummyProtocol()
      t = asyncio.Task(loop.create_connection(c, '192.168.1.143', '6600'))
      try:
          # Wait for 3 seconds, then raise TimeoutError
          trans, proto = await asyncio.wait_for(t, timeout=3)
          print("Connected to &lt;192.168.1.143:6600&gt;.")
          return proto
      except (asyncio.TimeoutError, OSError) as e:
          print("Could not connect to &lt;192.168.1.143:6600&gt;. Trying again ...")
          if isinstance(e, OSError):
              log.exception(e)
  
  
  def shutdown(proto, loop):
      # http://stackoverflow.com/a/30766124/1230358
      print("Shutdown of DummyProtocol initialized ...")
      proto.close()
      # give the coros time to finish
      time.sleep(2)
  
      # cancel all other tasks
      # for task in asyncio.Task.all_tasks():
      #    task.cancel()
  
      # stopping the event loop
      if loop:
          print("Stopping event loop ...")
          loop.stop()
  
      print("Shutdown complete ...")    
  
  
  if __name__ == "__main__":
  
      loop = asyncio.get_event_loop()
  
      cmd_queue = asyncio.Queue()
      res_queue = asyncio.Queue()
  
      dummy_proto = loop.run_until_complete(connect(loop))
  
      for signame in ('SIGINT','SIGTERM'):
          loop.add_signal_handler(getattr(signal, signame), functools.partial(shutdown, dummy_proto, loop))
  
      try:
          loop.run_forever()
      except KeyboardInterrupt:
          pass
      finally:
          loop.close()
  </code></pre>
  
  <p>what gives me the following output if CTRL-C is pressed:</p>
  
  <pre><code>Connected to &lt;192.168.1.143:6600&gt;.
  Ready for sending commands
  Waiting for commands coming in ...
  Waiting for commands coming in ...
  Waiting for commands coming in ...
  Waiting for commands coming in ...
  ^CShutdown of DummyProtocol initialized ...
  Closing protocol
  Stopping event loop ...
  Shutdown complete ...
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;DummyProtocol._send_commands() running at ./dummy.py:45&gt; wait_for=&lt;Future pending cb=[Task._wakeup()]&gt;&gt;
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;Queue.get() running at /usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/queues.py:168&gt; wait_for=&lt;Future pending cb=[Task._wakeup()]&gt; cb=[_release_waiter(&lt;Future pendi...sk._wakeup()]&gt;)() at /usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/tasks.py:344]&gt;
  Exception ignored in: &lt;generator object Queue.get at 0x10594b468&gt;
  Traceback (most recent call last):
    File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/queues.py", line 170, in get
    File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/futures.py", line 227, in cancel
    File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/futures.py", line 242, in _schedule_callbacks
    File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/base_events.py", line 447, in call_soon
    File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/base_events.py", line 456, in _call_soon
    File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/base_events.py", line 284, in _check_closed
  RuntimeError: Event loop is closed
  </code></pre>
  
  <p>I'm not very experienced with asyncio, so I'm pretty sure that I'm missing something important here. What really gives me headaches is the part of the output after <code>Shutdown complete ...</code>. Beginning with <code>Task was destroyed but it is pending!</code>, I have to admit that I have no idea what's going on. I had a look on other questions but couldn't get it to work. So, why is this code outputting stuff like <code>Task was destroyed but it is pending! aso.</code>and how can cleany close the coroutines?</p>
  
  <p>Thank's for your help!</p>