Refcount the thread_state.asynchronous flag
@@ -319,11 +319,15 @@ def sync(loop, func, *args, callback_timeout=None, **kwargs):
@gen.coroutine
def f():
+ # We flag the thread state asynchronous, which will make sync() call
+ # within `func` use async semantic. In order to support concurrent
+ # calls to sync(), `asynchronous` is used as a ref counter.
+ thread_state.asynchronous = getattr(thread_state, "asynchronous", 0)
+ thread_state.asynchronous += 1
try:
if main_tid == threading.get_ident():
raise RuntimeError("sync() called from thread of running loop")
yield gen.moment
- thread_state.asynchronous = True
future = func(*args, **kwargs)
if callback_timeout is not None:
future = asyncio.wait_for(future, callback_timeout)
@@ -331,7 +335,8 @@ def sync(loop, func, *args, callback_timeout=None, **kwargs):
except Exception as exc:
error[0] = sys.exc_info()
finally:
- thread_state.asynchronous = False
+ assert thread_state.asynchronous > 0
+ thread_state.asynchronous -= 1
e.set()
loop.add_callback(f)
