Server connected by ('72.236.109.185', 58833) at Sun Apr 25 08:16:34 2010
Server connected by ('72.236.109.185', 58834) at Sun Apr 25 08:16:34 2010
Server connected by ('72.236.109.185', 58835) at Sun Apr 25 08:16:34 2010
Server connected by ('72.236.109.185', 58836) at Sun Apr 25 08:16:34 2010
[...]$ ps -f
UID PID PPID C STIME TTY TIME CMD
5693094 3837 30778 0 08:10 pts/0 00:00:00 python fork-server-signal.py
5693094 9666 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9667 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9668 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9670 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9674 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9678 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9681 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9682 3837 0 08:16 pts/0 00:00:00 python fork-server-signal.py
5693094 9722 30778 0 08:16 pts/0 00:00:00 ps -f
5693094 30778 30772 0 04:23 pts/0 00:00:00 -bash
[...]$ ps -f
UID PID PPID C STIME TTY TIME CMD
5693094 3837 30778 0 08:10 pts/0 00:00:00 python fork-server-signal.py
5693094 10045 30778 0 08:16 pts/0 00:00:00 ps -f
5693094 30778 30772 0 04:23 pts/0 00:00:00 –bash
And now that I’ve shown you how to use signal handling to reap children automatically
on Linux, I should underscore that this technique is not universally supported across
all flavors of Unix. If you care about portability, manually reaping children as we did
in Example 12-4 may still be desirable.
Why multiprocessing doesn’t help with socket server portability
In Chapter 5, we learned about Python’s new multiprocessing module. As we saw, it
provides a way to start function calls in new processes that is more portable than the
os.fork call used in this section’s server code, and it runs processes instead of threads
to work around the thread GIL in some scenarios. In particular, multiprocessing works
on standard Windows Python too, unlike direct os.fork calls.
I experimented with a server variant based upon this module to see if its portability
might help for socket servers. Its full source code is in the examples package in file
multi-server.py, but here are its important bits that differ:
...rest unchanged from fork-server.py...
from multiprocessing import Process
def handleClient(connection):
print('Child:', os.getpid()) # child process: reply, exit
time.sleep(5) # simulate a blocking activity
while True: # read, write a client socket
data = connection.recv(1024) # till eof when socket closed
...rest unchanged...
def dispatcher(): # listen until process killed
Handling Multiple Clients | 813