Skip to content

Commit 5fa24bb

Browse files
committed
Exit cleanly the interactive client on ^C.
Fix #1599.
1 parent d0e60d3 commit 5fa24bb

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

src/websockets/cli.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,15 @@ async def interactive_client(uri: str) -> None:
121121
try:
122122
await asyncio.wait(
123123
[incoming, outgoing],
124+
# Clean up and exit when the server closes the connection
125+
# or the user enters EOT (^D), whichever happens first.
124126
return_when=asyncio.FIRST_COMPLETED,
125127
)
126-
except (KeyboardInterrupt, EOFError): # ^C, ^D # pragma: no cover
128+
# asyncio.run() cancels the main task when the user triggers SIGINT (^C).
129+
# https://docs.python.org/3/library/asyncio-runner.html#handling-keyboard-interruption
130+
# Clean up and exit without re-raising CancelledError to prevent Python
131+
# from raising KeyboardInterrupt and displaying a stack track.
132+
except asyncio.CancelledError: # pragma: no cover
127133
pass
128134
finally:
129135
incoming.cancel()
@@ -165,4 +171,8 @@ def main(argv: list[str] | None = None) -> None:
165171
except ImportError: # readline isn't available on all platforms
166172
pass
167173

168-
asyncio.run(interactive_client(args.uri))
174+
# Remove the try/except block when dropping Python < 3.11.
175+
try:
176+
asyncio.run(interactive_client(args.uri))
177+
except KeyboardInterrupt: # pragma: no cover
178+
pass

0 commit comments

Comments
 (0)