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

SniffIO doesn't detect asyncio when running sync callbacks in loop #35

Open
tapetersen opened this issue Nov 21, 2022 · 4 comments · May be fixed by #39
Open

SniffIO doesn't detect asyncio when running sync callbacks in loop #35

tapetersen opened this issue Nov 21, 2022 · 4 comments · May be fixed by #39

Comments

@tapetersen
Copy link

As discussed in agronholm/anyio#501 SniffIO doesn't detect it's running in asyncio when executing a callback added with loop.call_soon_threadsafe since it relies on asyncio.get_current_task for detection.

Using asyncio.get_running_loop should from my understanding work for all cases the current detection does and also allow detection in the case of executing in the event loop but not having a task.

I'll add a PR with the change implemented as well.

@tapetersen
Copy link
Author

I know we discussed this in AnyIO @agronholm and you suggested trying to fix it here. Is there something I could do to make it easier to resolve this or is it a bad idea (regarding the linked MR)

@oremanj
Copy link
Member

oremanj commented Jun 14, 2023

What are you trying to achieve by having sniffio return something in particular when invoked from a sync callback? I tend to think of sniffio as being for answering the question "what library can I await things from right now", and from a sync callback the answer is "none of them". If we want it to answer the question "what library can I spawn tasks with right now", there's not necessarily even an unambiguous answer, because it's possible to run multiple event loops in the same thread using guest mode or trio-asyncio.

I'm not necessarily opposed to changing the behavior here. It would definitely be nice (and good for performance) to be able to set the sniffio loop once at the start of run, instead of setting and unsetting it around every task tick. But I want to make sure we have a coherent story for what sniffio's purpose is and how its semantics achieve that purpose, and I'm worried that supporting sniffing from a non-task context might muddy that.

@tapetersen
Copy link
Author

@oremanj in my case it was just a to be able to allow anyio to create Events in the sync callback (which created structures containing them which would be awaited later later in the same loop by an async callback).

I realize you may not have that context on this level but in this case it was even from threads created by to_thread and then calling with from_thread.run_sync so in some sense they were already in an async context.

For my case this is mostly semantic and I could change the callback to async to allow the detection (but I, in particularly this case, like signaling that it's atomic with respect to the loop thread with no awaits by defining it sync).

For discussion if you want perspective in figuring it out my ,possibly inaccurate since I'm not testing right now, view is that this works in trio when called by from_thread since detection there is based on an explicit contextvar which I think trio propagates with the call while asyncio detection is based on get_running_task which fails since there is no task even if we're in fact explicitly running in an eventloop.

In the case of trio's guest mode it would indeed maybe give the wrong answer if the contextvar telling we're in fact in trio-context doesn't get passed and we fall back to get_current_loop and report asyncio for a sync callback scheduled from trio (but ran in asyncio).

I'm not sure how trio-asyncio works in this case but the semantics I would have wished was probably (in the case where we are in a callback scheduled with a particular libraries API that we get the library's flavour even if the loop for example is asyncio)

@oremanj oremanj linked a pull request Jul 11, 2023 that will close this issue
@gschaffner
Copy link
Member

gschaffner commented Jul 14, 2023

this works in trio when called by from_thread since detection there is based on an explicit contextvar which I think trio propagates with the call while asyncio detection is based on get_running_task which fails since there is no task even if we're in fact explicitly running in an eventloop.

@tapetersen have you seen/had a chance to test agronholm/anyio#524? i think the problem you encountered with anyio.from_thread.run_sync (agronholm/anyio#501) has been fixed downstream.

(that AnyIO fix doesn't actually address this post, but it should have addressed the AnyIO bug that prompted this post.)

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

Successfully merging a pull request may close this issue.

3 participants