Skip to content

Commit a41c831

Browse files
committed
Document how to shut down the server.
Fix #124, #103.
1 parent e58c1ac commit a41c831

File tree

3 files changed

+62
-3
lines changed

3 files changed

+62
-3
lines changed

docs/deployment.rst

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,39 @@ Deployment
44
The author of ``websockets`` isn't aware of best practices for deploying
55
network services based on :mod:`asyncio`.
66

7-
He suggests running a Python script similar to the :ref:`server example
8-
<server-example>`, perhaps inside a supervisor if you deem it useful.
7+
You can run a script similar to the :ref:`server example <server-example>`,
8+
inside a supervisor if you deem that useful.
9+
10+
You can also add a wrapper to daemonize the process. Third-party libraries
11+
provide solutions for that.
912

1013
If you can share knowledge on this topic, please file an issue_. Thanks!
1114

1215
.. _issue: https://github.com/aaugustin/websockets/issues/new
16+
17+
Graceful shutdown
18+
-----------------
19+
20+
You may want to close connections gracefully when shutting down the server,
21+
perhaps after executing some cleanup logic.
22+
23+
The proper way to do this is to call the ``close()`` method of the object
24+
returned by :func:`~websockets.server.serve`, then wait for ``wait_closed()``
25+
to complete.
26+
27+
Tasks that handle connections will be cancelled, in the sense that
28+
:meth:`~websockets.protocol.WebSocketCommonProtocol.recv` raises
29+
:exc:`~asyncio.CancelledError`.
30+
31+
On Unix systems, shutdown is usually triggered by sending a signal.
32+
33+
Here's a full example (Unix-only):
34+
35+
.. literalinclude:: ../example/shutdown.py
36+
37+
38+
It's more difficult to achieve the same effect on Windows. Some third-party
39+
projects try to help with this problem.
40+
41+
If your server doesn't run in the main thread, look at
42+
:func:`~asyncio.AbstractEventLoop.call_soon_threadsafe`.

example/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
async def hello():
77
async with websockets.connect('ws://localhost:8765') as websocket:
8-
8+
while True:
99
name = input("What's your name? ")
1010
await websocket.send(name)
1111
print("> {}".format(name))

example/shutdown.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/usr/bin/env python
2+
3+
import asyncio
4+
import signal
5+
import websockets
6+
7+
async def echo(websocket, path):
8+
while True:
9+
try:
10+
msg = await websocket.recv()
11+
except websockets.ConnectionClosed:
12+
pass
13+
else:
14+
await websocket.send(msg)
15+
16+
loop = asyncio.get_event_loop()
17+
18+
# Create the server.
19+
start_server = websockets.serve(echo, 'localhost', 8765)
20+
server = loop.run_until_complete(start_server)
21+
22+
# Run the server until SIGTERM.
23+
stop_server = asyncio.Future()
24+
loop.add_signal_handler(signal.SIGTERM, stop_server.set_result, None)
25+
loop.run_until_complete(stop_server)
26+
27+
# Shut down the server.
28+
server.close()
29+
loop.run_until_complete(server.wait_closed())

0 commit comments

Comments
 (0)