Skip to content

Conversation

@pmeier
Copy link

@pmeier pmeier commented Oct 29, 2025

Summary

One possible solution for #2167.

Checklist

  • I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • 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.

@Kludex
Copy link
Owner

Kludex commented Oct 29, 2025

This does make sense, but do you know why it happens?

@pmeier
Copy link
Author

pmeier commented Oct 29, 2025

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 #2167 (comment) for details.

@pmeier pmeier marked this pull request as ready for review November 3, 2025 15:10
@pmeier pmeier changed the title explicitly start with empty context explicitly start ASGI run with empty context Nov 3, 2025
@pmeier
Copy link
Author

pmeier commented Nov 16, 2025

Ping @Kludex

@Kludex
Copy link
Owner

Kludex commented Nov 17, 2025

We need to fix it in httptools as well, and do you think you can create a test that reproduces the issue?

@pmeier
Copy link
Author

pmeier commented Nov 17, 2025

@Kludex

We need to fix it in httptools as well

Can you explain that? Are you talking about

uvicorn/pyproject.toml

Lines 41 to 44 in 8ae0bcb

[project.optional-dependencies]
standard = [
"colorama>=0.4; sys_platform == 'win32'",
"httptools>=0.6.3",

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 #2167 (comment).

Can you decide if you want to go with the solution before I put in more work?

@Kludex
Copy link
Owner

Kludex commented Nov 21, 2025

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.

@pmeier
Copy link
Author

pmeier commented Nov 21, 2025

@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.

Worse, while writing the test I realized that my attempted fix, i.e. being explicit about an empty context does not work. At least we now know that the test will actually fail on a regression.

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 this pull request may close these issues.

2 participants