title: Correct use/constraints of use, of nest_asyncio?
body: <p>I'm working on making a previously sync webserver as sync one.
  Most of my functions are sync and I'd like to simply make async calls from existing code to avoid async creep. nest_asyncio appears to allow this by making run_until_complete re-entrant.</p>
  
  <p>However, while this works for 1 reentrant call, I get a deadlock with two: </p>
  
  <pre><code>import asyncio
  import functools
  import time
  from random import random
  import nest_asyncio
  nest_asyncio.apply()
  
  def sync(corot, loop=None):
      """
      Make a synchronous function from an asynchronous one.
      :param corot:
      :return:
      """
      if loop is None:
          loop = asyncio.get_event_loop()
      result, = loop.run_until_complete(asyncio.gather(corot))
      return result
  
  async def sync_to_corountine(func, *args, **kw):
      """
      Make a coroutine from a synchronous function.
      """
      try:
          return func(*args, *kw)
      finally:
          # every async needs an await.
          await asyncio.sleep(0)
  
  
  
  
  def main():
      async def background(timeout):
          await asyncio.sleep(timeout)
          print(f"Background: {timeout}")
  
      loop = asyncio.get_event_loop()
      # Run some background work to check we are never blocked
      bg_tasks = [
          loop.create_task(background(i))
          for i in range(10)
      ]
  
  
  
      async def long_running_async_task(result):
          # Simulate slow IO
          print(f"...START long_running_async_task [{result}]")
          await asyncio.sleep(1)
          print(f"...END   long_running_async_task [{result}]")
          return result
  
      def sync_function_with_async_dependency(result):
          print(f"...START sync_function_with_async_dependency [{result}]")
          result = sync(long_running_async_task(result), loop=loop)
          print(f"...END   sync_function_with_async_dependency [{result}]")
          return result
  
      # Call sync_function_with_async_dependency
      # One reentrant task is OK
      # Multiple reentrant tasks=&gt;fails to exit
      n = 2
      for i in range(n):
          bg_tasks.append(sync_to_corountine(sync_function_with_async_dependency, i))
      # for i in range(n):
      #     bg_tasks.append(long_running_async_task(i))
  
      # OK
      # bg_tasks.append(long_running_async_task(123))
      # bg_tasks.append(long_running_async_task(456))
  
      task = asyncio.gather(*bg_tasks)  # , loop=loop)
      loop.run_until_complete(task)
  
  if __name__ == '__main__':
      main()
  
  </code></pre>
  
  <pre><code>...START sync_function_with_async_dependency [0]
  ...START sync_function_with_async_dependency [1]
  Background: 0
  ...START long_running_async_task [0]
  ...START long_running_async_task [1]
  Background: 1
  ...END   long_running_async_task [0]
  ...END   long_running_async_task [1]
  ...END   sync_function_with_async_dependency [1]
  Background: 2
  Background: 3
  Background: 4
  </code></pre>
  
  <p>... we are missing</p>
  
  <pre><code>...END   sync_function_with_async_dependency [0]
  </code></pre>
  
  <p>Am I using nest_asyncio correctly?</p>