explicitly start ASGI run with empty context
Summary
One possible solution for #2167.
Checklist
- [x] I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
- [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
- [ ] I've updated the documentation accordingly.
This does make sense, but do you know why it happens?
~I think so, yes. asyncio does not clean up the context when starting a new task. This is why they added the context keyword argument in 3.11 to make this simpler. The documentation states~
~> The current context copy is created when no context is provided.~
~So far I only have a not-so-minimal reproducer: https://github.com/pmeier/asyncio-contextvars-pollution. Using the patch in this PR, the pollution is resolved.~
~How exactly it happens in the first place, I don't know yet. My goal is to get to a reproducer that just depends on uvicorn that I hopefully can put into a unittest. This could serve as testing ground to find the underlying reason.~
~Finally, my working hypothesis as for why this is not happening by uvloop is that they are not a drop-in replacement for this specific behavior of asyncio. On the surface it seems that they are replicating it correctly, but I haven't dug any deeper just yet.~
@Kludex I was wrong. This is a bug in asyncio. See https://github.com/Kludex/uvicorn/issues/2167#issuecomment-3481001395 for details.
Ping @Kludex
We need to fix it in httptools as well, and do you think you can create a test that reproduces the issue?
@Kludex
We need to fix it in httptools as well
Can you explain that? Are you talking about
https://github.com/Kludex/uvicorn/blob/8ae0bcbecb0a655789abf0c2dd4200848fc68a30/pyproject.toml#L41-L44
https://github.com/MagicStack/httptools
do you think you can create a test that reproduces the issue?
Yeah, likely. I haven't written one, because the solution is not the only one that is possible to fix the issue. See https://github.com/Kludex/uvicorn/issues/2167#issuecomment-3481001395.
Can you decide if you want to go with the solution before I put in more work?
Can you decide if you want to go with the solution before I put in more work?
It's a bit unfortunate we need to do it here, but I guess it's fine.
Can you explain that? Are you talking about
We have a h11_impl.py and httptools_impl.py that has analogous logic.
@Kludex
It's a bit unfortunate we need to do it here, but I guess it's fine.
There is an open PR python/cpython#141158 that'll hopefully fix this for Python >=3.15. But until that there is no way around doing this in uvicorn if we don't want to tell users to use uvloop by default.
can create a test that reproduces the issue
I've added a test that should reproduce the issue. However, it also won't pass right now I don't know why yet. Trying my fix on reproducers outside of the test suite works just fine. Thus, my working assumption is that one of the mock components does not behave like the real component would. I'll try to find out which one.
Ping @Kludex