Raise ConnectionResetError if transport is None#11761
Raise ConnectionResetError if transport is None#11761agners wants to merge 4 commits intoaio-libs:masterfrom
Conversation
|
The assertion is because the code expects it to never be None in this scenario, so I'm not sure this is the correct fix. I'll use your test and try to figure out if there's a better solution later. |
Wait, sorry, your test literally just assigns the transport to None. We need the actual set of steps that causes this to happen in production. |
|
Running through the code, I think the steps that may reproduce this would look like:
I think the WebSocketWriter that is returned from .prepare() is responsible for raising exceptions related to the client disconnecting. Therefore, my first thought is that we should probably figure out a fix that ensures the (potentially closed) transport is always available inside .prepare(). |
|
I think setting the transport to None is something that has been copied from asyncio, but I'm not clear if there's a real reason for that. Maybe we can just avoid setting to None, which would greatly simplify our type checking. @bdraco Any thoguhts? |
Yeah sorry, I realize this test is not ideal, but triggering a race condition is also not really a good idea for a pytest.
Right, I think that is pretty much the sequence we see in production. I have a reproducer which allows to trigger the bug in our use case (Home Assistant Supervisor): home-assistant/supervisor#6241, specifically home-assistant/supervisor#6241 (comment).
Hm, I guess that would make the transport to raise a closed connection exception or similar, this sounds like a good approach to me. |
Following the steps I outlined, we should be able to reproduce it with minimal timing concerns. We have many similar tests that reproduce other race conditions. |
When a client disconnects immediately after connecting, the transport might become None. Replace the assert with a ConnectionResetError, which is consistent with the existing aiohttp exception hierarchy and the documented guidance to handle OSError for peer disconnection. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
9f20389 to
ecc2177
Compare
for more information, see https://pre-commit.ci
I've added such a test, along with using an |
Perfect, thanks for that. I'll have a little play with it later and see if we can get rid of the None checks. |
|
I had a little go in #12244. It's pretty awkward to remove the None entirely, as you'd be left with an AttributeError until connection_made() is called to set the transport initially. I think we'll just leave it as is for now. |
Co-authored-by: Sam Bull <aa6bs0@sambull.org>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #11761 +/- ##
==========================================
- Coverage 99.10% 99.10% -0.01%
==========================================
Files 130 130
Lines 45402 45425 +23
Branches 2399 2401 +2
==========================================
+ Hits 44997 45019 +22
Misses 273 273
- Partials 132 133 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
| transport = request.transport | ||
| assert transport is not None | ||
| if transport is None: | ||
| raise ConnectionResetError("Connection lost") |
There was a problem hiding this comment.
Is there a version of the test that allows us to cover this line?
What do these changes do?
When a client disconnects immediately after connecting, the transport might become None. This should not lead to an assertion, since this can happen in real-world scenarios. Use a RuntimeException instead.
Are there changes in behavior for the user?
A WebSocket connection disconnecting early will no longer lead to a assertion but a RuntimeException instead.
Is it a substantial burden for the maintainers to support this?
Related issue number
Checklist
CONTRIBUTORS.txtCHANGES/foldername it
<issue_or_pr_num>.<type>.rst(e.g.588.bugfix.rst)if you don't have an issue number, change it to the pull request
number after creating the PR
.bugfix: A bug fix for something the maintainers deemed animproper undesired behavior that got corrected to match
pre-agreed expectations.
.feature: A new behavior, public APIs. That sort of stuff..deprecation: A declaration of future API removals and breakingchanges in behavior.
.breaking: When something public is removed in a breaking way.Could be deprecated in an earlier release.
.doc: Notable updates to the documentation structure or buildprocess.
.packaging: Notes for downstreams about unobvious side effectsand tooling. Changes in the test invocation considerations and
runtime assumptions.
.contrib: Stuff that affects the contributor experience. e.g.Running tests, building the docs, setting up the development
environment.
.misc: Changes that are hard to assign to any of the abovecategories.
Make sure to use full sentences with correct case and punctuation,
for example:
Use the past tense or the present tense a non-imperative mood,
referring to what's changed compared to the last released version
of this project.