-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
ProactorEventLoop raises unhandled ConnectionResetError #83191
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
Comments
We have a snippet of code that runs perfectly fine using the The traceback is the following. The exception cannot be caught within the asyncio application itself (e.g., it is not attached to any Future or propagated in a coroutine). It probably propagates in File "C:\Python38\lib\asyncio\proactor_events.py", line 768, in _loop_self_reading I can see that in In order to reproduce, run the following snippet on Python 3.8: from prompt_toolkit import prompt # pip install prompt_toolkit
while 1:
prompt('>') Hold down the enter key, and it'll trigger quickly. |
Suppressing Although I'm not sure what it causing the error, and whether we need to handle it somehow. |
ConnectionResetError means that the pipe socket is closed. Was the event loop closed? Can you provide a reproducer? Can you try to get debug logs to see what's going on? |
Thanks Victor for the reply. It looks like it's the self-socket in the BaseProactorEventLoop that gets closed. It's exactly this FD for which the exception is raised. We don't close the event loop anywhere. I also don't see Debug logs don't provide any help. I'm looking into a reproducer. |
It looks like the following code will reproduce the issue:
Leave it running on Windows, in Python 3.8 for a few seconds, then it starts spawning |
Even simpler, the following code will crash after so many iterations:
Adding a little sleep of 0.01s after So, to me it looks like the cancellation of the |
I just spent some time digging into this. Each call to cpython/Lib/asyncio/windows_events.py Lines 312 to 325 in 1ed6161
The comment at line 321 is not entirely accurate: the future will not resolve in the future, but it may have already resolved, and added its callback to the call_soon queue. This callback will run if the event loop is restarted again. Since This appears to be fairly harmless except for noise in the logs when only one of the loops is stopped cleanly. I believe the simplest fix is for |
Please take a look at this as well: |
Here is another way to reproduce this (or an extremely similar) error without a loop. Since may be a race condition, I'm not sure this works 100% of the time on all machines - but it did on several machines I tried.
|
Any input from the asyncio experts? I don't have an issue with handling the exception in this case, and hopefully when someone is up to the task of dealing with the range of edge cases throughout this loop implementation, hopefully they can get the ordering of waits right. |
I've posted a pull request with a test and fix: #22017. It's a more targeted fix than cmeyer's PR (which I didn't even notice until now due to unfamiliarity with the BPO UI) |
Thanks, Ben! |
I've been seeing failures on the Win10 buildbot 3.x branch that seem to correlate with the timing of this change - could there be some further work needed on Windows? Or, if it's a test-only artifact and the warnings are innocuous, something to ignore the output during the tests? Specifically, the following warnings occur during test_asyncio: See https://buildbot.python.org/all/#/builders/146/builds/23 for the first failing build. |
I can confirm that those warnings appear to be coming from the test I added here. I'm not sure how to interpret them, though - what does it mean for the main thread to be dangling? |
I'm guessing the warning appears odd as we're seeing a thread shutdown data race. The message is produced by threading_cleanup in support/threading_helper.py, and it appears that between the first and second lines one of the initially dangling threads goes away, so the only one left to be enumerated is the main thread, at which point the function is simply listing all threads currently alive. But by that point it's just the main thread remaining. I notice in the test that you have a comment about needing to wait for f to complete or you get a warning about thread not shutting down cleanly. Was that a similar warning? The run_until_complete(f) line seems to have no effect on the buildbot. If I added a small sleep at the end of the test the warnings go away on the buildbot. The buildbot is a fairly fast machine, so perhaps the test just needs to wait somehow for the event loop to fully shut down or something. The most direct cause of the warnings seems to be the self.loop.close() call - if I just comment that out the test runs warning-free without any extra delay needed. I don't know much about asyncio tests, but it would appear the close call in the test defeats some of the logic in the close_loop teardown code that runs under TestCase (in utils.py), which under Windows is just a call to run_until_complete(loop.shutdown_default_executor()). If I add that same call to the test prior to the close it also passes cleanly. So if closing the loop in the test itself is crucial, I'd suggest including the extra run_until_complete call. If closing isn't crucial to the test, simply removing it seems to address the issue. I'm not sure if its removal then has any implications for the extra run_until_complete(f) call in the test, as I can't see any impact from that on the buildbot. |
I've fixed the test and added some commentary about the different levels of clean shutdown we must do to quiet all the warnings: #22066 |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: