You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An upstream change in CPython >= 3.12 changes the behaviour of asyncio.Server.serve_forever() to wait for all clients to disconnect voluntarily before returning upon cancellation. There is discussion to change this behaviour, but no patch has been finalized yet python/cpython#123720.
websockets is affected, because it relies directly on serve_forever(). Common patterns for running a server will start blocking in Python >= 3.12 upon cancellation until all clients disconnect.
serve() context manager + serve_forever(), described in the Quick examples.
This is the easiest to reproduce the problem: Create the script from the example, start the script, connect a client (any TCP client works, or a websockets client from same example page), then stop the server via Ctrl-C.
Waiting for an arbitrary future continues to work, also described in websockets.asyncio.server.serve docs. Upon cancellation, the serve() context manager is exited and will shut down the server including all connected clients.
Not sure how to continue here. This issue describes the problem and will hopefully save others the time to research. We could update all examples in the docs to use the only working pattern. Or add a note at least to server.serve mentioning the issue. To me it seems likely that the issue will be fixed in CPython and also backported to 3.12, so implementing a custom serve_forever() may not be worthwhile.
The text was updated successfully, but these errors were encountered:
Thank you for investigating the situation and reporting your findings. websockets sticks to Python's behavior in such cases because having a slightly different behavior from the stdlib is likely to cause even more confusion.
We could update all examples in the docs to use the only working pattern.
I just made the opposite change because the await asyncio.get_running_loop().create_future() pattern didn't feel intuitive and didn't look popular 🤦
I just made the opposite change because the await asyncio.get_running_loop().create_future() pattern didn't feel intuitive and didn't look popular 🤦
I feel the same way. serve_forever() was a great addition, helping to bring the behaviour of running a server in line with any other cancellable async task.
Looking at pypistats indicates there are ~ 24 % of package downloads >= 3.12 and hence affected by this issue.
What do you think of adding an admonition to the relevant docs pages? Assuming (hoping) that the CPython change is only temporary, it makes little sense to change all examples or introduce new API.
An upstream change in CPython >= 3.12 changes the behaviour of
asyncio.Server.serve_forever()
to wait for all clients to disconnect voluntarily before returning upon cancellation. There is discussion to change this behaviour, but no patch has been finalized yet python/cpython#123720.websockets is affected, because it relies directly on
serve_forever()
. Common patterns for running a server will start blocking in Python >= 3.12 upon cancellation until all clients disconnect.serve()
context manager +serve_forever()
, described in the Quick examples.This is the easiest to reproduce the problem: Create the script from the example, start the script, connect a client (any TCP client works, or a websockets client from same example page), then stop the server via Ctrl-C.
Plain
serve()
+serve_forever()
, described inwebsockets.asyncio.server.serve
API docs.Waiting for an arbitrary future continues to work, also described in
websockets.asyncio.server.serve
docs. Upon cancellation, theserve()
context manager is exited and will shut down the server including all connected clients.Not sure how to continue here. This issue describes the problem and will hopefully save others the time to research. We could update all examples in the docs to use the only working pattern. Or add a note at least to
server.serve
mentioning the issue. To me it seems likely that the issue will be fixed in CPython and also backported to 3.12, so implementing a customserve_forever()
may not be worthwhile.The text was updated successfully, but these errors were encountered: