Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing test case for demonstrating why SyncToAsync.get_current_task has to occur for thread_critical Locals? #290

Open
kezabelle opened this issue Aug 16, 2021 · 1 comment

Comments

@kezabelle
Copy link
Contributor

My guess (given the complexity of juggling asyncio and threads is beyond my ken) is that there is a situation where, in Local._get_context_id, this bit is super important:

def _get_context_id(self):
    ...
    # First, pull the current task if we can
    context_id = SyncToAsync.get_current_task()
    context_is_async = True
    # OK, let's try for a thread ID
    if context_id is None:
        context_id = threading.current_thread()
        context_is_async = False
    if self._thread_critical:
        return context_id

Note how the presence of a current task is always checked first, falling back to the current thread if that's None and then returning the thread ID (or task ID?) immediately if it's thread critical.

But if I change it to:

def _get_context_id(self):
    if self._thread_critical:
        return threading.current_thread()
    from .sync import AsyncToSync, SyncToAsync
    ...

All the tests seem to pass, which is great if that's a valid change (because according to line profiler SyncToAsync.get_current_task is expensive, even ignoring #289), but I suspect it isn't valid, and is just missing from test coverage (which I'm wholly reliant on because I cannot fathom all of the underpinnings; As such, I'm incapable of writing a test to demonstrate it's importance, and I'm burdening someone else with doing so if appropriate, for which I apologise :))

@andrewgodwin
Copy link
Member

I barely understand the logic behind all those tests most days, so you're not alone here!

I'm unsure if this is a valid optimisation or not; it might be, because thread_critical is commented as "Set thread_critical to True to not allow locals to pass from an async Task to a thread it spawns", so it would make sense that it entrely ignores the actual async Task and instead is instrumented entirely off the current thread ID.

The case I would want to work through to check, though, is this other comment: "Thread-critical code will still be differentiated per-Task within a thread as it is expected it does not like concurrent access." - so, maybe we're missing a Locals test that makes sure different tasks in the same thread/async loop get different values?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants