Skip to content

Nested sync_to_async(thread_sensitive=True) calls do not run in the same thread. #357

Open
@charliesteele

Description

@charliesteele

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions