title: run_until_complete fails even after loop has been stopped
body: <p>Im trying to write a SIGTERM-handler that will have my <strong>run_forever()</strong>-loop</p>
  
  <ul>
  <li>Stop accepting new tasks.</li>
  <li>Complete running tasks.</li>
  <li>Shutdown.</li>
  </ul>
  
  <p>Here is a learning-demo I wrote:</p>
  
  <pre class="lang-py prettyprint-override"><code>import asyncio
  import signal
  import logging
  
  logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s [%(name)s]: %(message)s', datefmt='%H:%M:%S')
  _log = logging.getLogger(__name__)
  
  
  class Looper:
      def __init__(self, loop):
          self._loop = loop
          self._shutdown = False
          signal.signal(signal.SIGINT, self._exit)
          signal.signal(signal.SIGTERM, self._exit)
  
      def _exit(self, sig, frame):
          name = signal.Signals(sig).name
          _log.info(f"Received shutdown-signal: {sig} ({name})")
          self._shutdown = True
          self._loop.stop() # &lt;&lt; Stopping the event loop here.
          _log.info(f"Loop stop initiated.")
          pending = asyncio.all_tasks(loop=self._loop)
          _log.info(f"Collected {len(pending)} tasks that have been stopped.")
          if pending:
              _log.info("Attempting to gather pending tasks: " + str(pending))
              gatherer_set = asyncio.gather(*pending, loop=self._loop)
              # self._loop.run_until_complete(gatherer_set) # &lt;&lt; "RuntimeError: This event loop is already running"
          _log.info("Shutting down for good.")
  
      async def thumper(self, id, t):
          print(f"{id}: Winding up...")
          while not self._shutdown:
              await asyncio.sleep(t)
              print(f'{id}: Thump!')
          print(f'{id}: Thud.')
  
  
  loop = asyncio.get_event_loop()
  lp = Looper(loop)
  loop.create_task(lp.thumper('North Hall', 2))
  loop.create_task(lp.thumper('South Hall', 3))
  loop.run_forever()
  _log.info("Done.")
  </code></pre>
  
  <p>Both on Windows 10 and Debian 10 above script reacts to SIGINT and produces the output</p>
  
  <pre><code>North Hall: Winding up...
  South Hall: Winding up...
  North Hall: Thump!
  South Hall: Thump!
  North Hall: Thump!
  South Hall: Thump!
  North Hall: Thump!
  09:55:53 INFO [__main__]: Received shutdown-signal: 2 (SIGINT)
  09:55:53 INFO [__main__]: Loop stop initiated.
  09:55:53 INFO [__main__]: Collected 2 tasks that have been stopped.
  09:55:53 INFO [__main__]: Attempting to gather pending tasks: {&lt;Task pending coro=&lt;Looper.thumper() running at amazing_grace.py:42&gt; wait_for=&lt;Future pending cb=[&lt;TaskWakeupMethWrapper object at 0x02F91BF0&gt;()]&gt;&gt;, &lt;Task pending coro=&lt;Looper.thumper() running at amazing_grace.py:42&gt; wait_for=&lt;Future pending cb=[&lt;TaskWakeupMethWrapper object at 0x02F91C10&gt;()]&gt;&gt;}
  09:55:53 INFO [__main__]: Shutting down for good.
  09:55:53 INFO [__main__]: Done.
  </code></pre>
  
  <p>Sadly, the "Thud."-lines, signifying that the <strong>thumper(..)</strong> demo calls have actually
  concluded, won't show. I guess, this is because the "gather" just gets me a set
  of unfulfilled futures. However, if I dare activate the <strong>run_until_complete()</strong>-
  line, even though it comes <em>behind</em> the <strong>self._loop.stop()</strong>, the output
  ends as follows:</p>
  
  <pre><code>[...]
  10:24:25 INFO [__main__]: Collected 2 tasks that have been stopped.
  10:24:25 INFO [__main__]: Attempting to gather pending tasks: {&lt;Task pending coro=&lt;Looper.thumper() running at amazing_grace.py:41&gt; wait_for=&lt;Future pending cb=[&lt;TaskWakeupMethWrapper object at 0x03E417D0&gt;()]&gt;&gt;, &lt;Task pending coro=&lt;Looper.thumper() running at amazing_grace.py:41&gt; wait_for=&lt;Future pending cb=[&lt;TaskWakeupMethWrapper object at 0x03E41BF0&gt;()]&gt;&gt;}
  Traceback (most recent call last):
    File "amazing_grace.py", line 50, in &lt;module&gt;
      loop.run_forever()
    File "C:\Python37\lib\asyncio\base_events.py", line 539, in run_forever
      self._run_once()
    File "C:\Python37\lib\asyncio\base_events.py", line 1739, in _run_once
      event_list = self._selector.select(timeout)
    File "C:\Python37\lib\selectors.py", line 323, in select
      r, w, _ = self._select(self._readers, self._writers, [], timeout)
    File "C:\Python37\lib\selectors.py", line 314, in _select
      r, w, x = select.select(r, w, w, timeout)
    File "amazing_grace.py", line 35, in _exit
      self._loop.run_until_complete(gatherer_set) # &lt;&lt; "This event loop is already running"
    File "C:\Python37\lib\asyncio\base_events.py", line 571, in run_until_complete
      self.run_forever()
    File "C:\Python37\lib\asyncio\base_events.py", line 526, in run_forever
      raise RuntimeError('This event loop is already running')
  RuntimeError: This event loop is already running
  </code></pre>
  
  <p>The question boils down to</p>
  
  <ul>
  <li>how to call or substitute <strong>run_until_complete(..)</strong> in this scenario, and</li>
  <li>why I see this "Loop is running"-error after stopping the loop.</li>
  </ul>
  
  <p>The program should run on <strong>Python 3.7</strong>, both under <strong>Windows 10</strong> and <strong>Linux</strong>.</p>
  
  <h1>Edit a couple of days later</h1>
  
  <p><em>As zaquest states in his/her answer, one asks for trouble when just assigning a signal handler and adding a <code>create_task</code> call inside it; as I observe, that routine may or may not run (even if there are no other tasks). So now I added a <code>sys.platform</code> check to see if the script runs under UNIX (). If it does I prefer the much more reliable <code>loop.add_signal_handler</code> to define the callback function, which is what I really need. Luckily UNIX is my main use-case. Main line:</em></p>
  
  <pre class="lang-py prettyprint-override"><code>self._loop.add_signal_handler(signal.signal(signal.SIGINT, self._exit, signal.SIGINT, None)
  </code></pre>
  
  <p><em>Why the platform check?: Following the doc, <a href="https://docs.python.org/3/library/asyncio-eventloop.html#unix-signals" rel="nofollow noreferrer">https://docs.python.org/3/library/asyncio-eventloop.html#unix-signals</a> , the loop.add_signal_handler() is not available on Windows, which is no real surprise thinking that the signals in question are UNIX lingo.</em></p>