title: asyncio CancelledError and KeyboardInterrupt
body: <p>I'm trying 2 ways to stop an infinite loop from running:  </p>
  
  <ul>
  <li><strong>supervisor_1</strong>: task is canceled programatically  </li>
  <li><strong>supervisor_2</strong>: task is stopped with Ctrl+C  </li>
  </ul>
  
  <p>While <strong>supervisor_2</strong> does not throw any errors at when interrupted, I cannot get <strong>supervisor_1</strong> from getting <code>Task was destroyed but it is pending!</code>. Any idea why ?</p>
  
  <p>Here is the code:</p>
  
  <pre><code>import asyncio
  import aioredis
  from functools import partial
  
  
  
  class Listener:
      def __init__(self, redis_conn):
          self.redis_conn = redis_conn
  
      async def forever(self, loop_name):
          counter = 0
          try:
              while True:
                  print('{}: {}'.format(loop_name, counter))
                  counter += 1
                  await asyncio.sleep(1)
          except asyncio.CancelledError:
              print('Task Cancelled')
              self.redis_conn.close()
              await self.redis_conn.wait_closed()
  
  
  async def supervisor_1(redis_conn):
      redis_conn = await redis_conn
  
      l = Listener(redis_conn)
  
      task = asyncio.ensure_future(
          asyncio.gather(l.forever('loop_1'), 
                         l.forever('loop_2')))
      await asyncio.sleep(2)
      task.cancel()
  
  
  async def supervisor_2(redis_conn):
      redis_conn = await redis_conn
  
      l = Listener(redis_conn)
      await asyncio.gather(l.forever('loop_1'), 
                           l.forever('loop_2'))
  
  
  if __name__ == '__main__':
      redis_conn = aioredis.create_pool(('localhost', 5003), db=1)
  
      loop = asyncio.get_event_loop()
      run = partial(supervisor_2, redis_conn=redis_conn)
      task = asyncio.ensure_future(run())
      try:
          loop.run_until_complete(task)
      except KeyboardInterrupt:
          print('Interruped !')
          task.cancel()
          loop.run_forever()
      finally:
          loop.close()
  </code></pre>
  
  <p><strong>@update</strong>:</p>
  
  <p>Thanks to @Gerasimov, here is a version that fix the problem, but somehow still raise errors from time to time on KeyboardInterrupt:  </p>
  
  <pre><code>async def supervisor(redis_conn):
      redis_conn = await redis_conn
  
      l = Listener(redis_conn)
  
      task = asyncio.ensure_future(
          asyncio.gather(l.forever('loop_1'), 
                         l.forever('loop_2'))
      )
      await asyncio.sleep(10)
      task.cancel()
      with suppress(asyncio.CancelledError):
          await task
  
  async def kill_tasks():
      pending = asyncio.Task.all_tasks()
      for task in pending:
          task.cancel()
          with suppress(asyncio.CancelledError):
              await task 
  </code></pre>
  
  <p>and  </p>
  
  <pre><code>if __name__ == '__main__':
      redis_conn = aioredis.create_pool(('localhost', 5003), db=1)
  
      loop = asyncio.get_event_loop()
      run = partial(supervisor, redis_conn=redis_conn)
      task = asyncio.ensure_future(run())
      try:
          loop.run_until_complete(task)
      except KeyboardInterrupt:
          print('Interruped !')
          loop.run_until_complete(kill_tasks())
      finally:
          loop.close()
  </code></pre>