Description
While testing, I noticed that nesting calls to async_to_sync
and sync_to_async
causes two calls to sync_to_async(thread_sensitive=True)
to run in different threads if you call sync_to_async(thread_sensitive=False)
in between those two calls. It seems that once sync_to_async
is called with thread_sensitive=False
, all subsequent (nested) calls with thread_sensitive=True
will run on the new parent thread rather than the main thread.
Example Code
import threading
from asgiref.sync import async_to_sync, sync_to_async
def method5():
print(f"Third call to sync_to_sync: {threading.get_ident()}")
async def method4():
print(f"Third call to async_to_sync: {threading.get_ident()}")
await sync_to_async(method5)()
def method3():
print(f"Second call to sync_to_async: {threading.get_ident()}")
async_to_sync(method4)()
async def method2():
print(f"Second call to async_to_sync: {threading.get_ident()}")
await sync_to_async(method3, thread_sensitive=False)()
def method1():
print(f"First call to sync_to_async: {threading.get_ident()}")
async_to_sync(method2)()
async def start():
print(f"First call to async_to_sync: {threading.get_ident()}")
await sync_to_async(method1)()
print(f"Main thread: {threading.get_ident()}")
async_to_sync(start)()
Output
Main thread: 4593313280
First call to async_to_sync: 123145368514560
First call to sync_to_async: 4593313280
Second call to async_to_sync: 123145368514560
Second call to sync_to_async: 123145373769728
Third call to async_to_sync: 123145368514560
Third call to sync_to_sync: 123145373769728
As you can see, the main thread is 4593313280
. The first call to sync_to_async(thread_sensitive=True)
runs on the main thread, as expected. The second call to sync_to_async(thread_sensitive=False)
creates a new thread (123145373769728
), as expected. However, the third and fourth calls to sync_to_async(thread_sensitive=True)
run on thread 123145373769728
rather than the main thread.
This seems to contradict the behavior described in the README:
All synchronous code called through SyncToAsync and marked with thread_sensitive should run in the same thread as each other (and if the outer layer of the program is synchronous, the main thread)
Is this a bug? Or is this expected behavior, and merely a gap in the documentation?
Thanks!
Charlie