flup-server
view flup/server/preforkserver.py @ 102:6ea1ffac1bcb
Restore check of the absolute number of children against maxSpare and
document rationale.
| author | Allan Saddi <allan@saddi.com> |
|---|---|
| date | Mon, 17 Aug 2009 12:42:43 -0700 |
| parents | e0e7e885f6cc |
| children | 57375deb17c3 |
line source
1 # Copyright (c) 2005 Allan Saddi <allan@saddi.com>
2 # All rights reserved.
3 #
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions
6 # are met:
7 # 1. Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer.
9 # 2. Redistributions in binary form must reproduce the above copyright
10 # notice, this list of conditions and the following disclaimer in the
11 # documentation and/or other materials provided with the distribution.
12 #
13 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 # SUCH DAMAGE.
24 #
25 # $Id$
43 pass
48 # If running Python < 2.4, require eunuchs module for socket.socketpair().
49 # See <http://www.inoi.fi/open/trac/eunuchs>.
54 # TODO: Other alternatives? Perhaps using os.pipe()?
68 """
69 A preforked server model conceptually similar to Apache httpd(2). At
70 any given time, ensures there are at least minSpare children ready to
71 process new requests (up to a maximum of maxChildren children total).
72 If the number of idle children is ever above maxSpare, the extra
73 children are killed.
75 If maxRequests is positive, each child will only handle that many
76 requests in its lifetime before exiting.
78 jobClass should be a class whose constructor takes at least two
79 arguments: the client socket and client address. jobArgs, which
80 must be a list or tuple, is any additional (static) arguments you
81 wish to pass to the constructor.
83 jobClass should have a run() method (taking no arguments) that does
84 the actual work. When run() returns, the request is considered
85 complete and the child process moves to idle state.
86 """
96 # Internal state of children. Maps pids to dictionaries with two
97 # members: 'file' and 'avail'. 'file' is the socket to that
98 # individidual child and 'avail' is whether or not the child is
99 # free to process requests.
111 """
112 The main loop. Pass a socket that is ready to accept() client
113 connections. Return value will be True or False indiciating whether
114 or not the loop was exited due to SIGHUP.
115 """
116 # Set up signal handlers.
121 # Don't want operations on main socket to block.
124 # Set close-on-exec
127 # Main loop.
129 # Maintain minimum number of children. Note that we are checking
130 # the absolute number of children, not the number of "available"
131 # children. We explicitly test against _maxSpare to maintain
132 # an *optimistic* absolute minimum. The number of children will
133 # always be in the range [_maxSpare, _maxChildren].
137 # Wait on any socket activity from live children.
144 # There are dead children that need to be reaped, ensure
145 # that they are by timing out, if necessary. Or there are some
146 # children that need to die.
154 raise
156 # Scan child sockets and tend to those that need attention.
158 # Receive status byte.
163 # Guess it really didn't need attention?
164 continue
165 raise
166 # Try to match it with a child. (Do we need a reverse map?)
170 # Set availability status accordingly.
173 # Didn't receive anything. Child is most likely
174 # dead.
181 # purging child
186 # Try to match it with a child. (Do we need a reverse map?)
192 break
194 # Reap children.
197 # See who and how many children are available.
202 # Need to spawn more children.
208 # Too many spares, kill off the extras.
218 # Clean up all child processes.
221 # Restore signal handlers.
224 # Return bool based on whether or not SIGHUP was received.
228 """
229 Closes all child sockets (letting those that are available know
230 that it's time to exit). Sends SIGINT to those that are currently
231 processing (and hopes that it finishses ASAP).
233 Any children remaining after 10 seconds is SIGKILLed.
234 """
235 # Let all children know it's time to go.
241 # Child is unavailable. SIGINT it.
246 raise
249 pass
251 # Set up alarm to wake us up after 10 seconds.
256 # Wait for all children to die.
262 break
268 # Forcefully kill any remaining children.
274 raise
277 """Cleans up self._children whenever children die."""
283 break
284 raise
286 break
293 """
294 Spawn a single child. Returns True if successful, False otherwise.
295 """
296 # This socket pair is used for very simple communication between
297 # the parent and its children.
308 raise
310 # Child
312 # Put child into its own process group.
315 # Restore signal handlers.
317 # Close copies of child sockets.
323 # Enter main loop.
326 pass
329 # Parent
337 """Override to provide access control."""
341 """Send message to parent, ignoring EPIPE and retrying on EAGAIN"""
350 # Wait for socket change before sending again
353 raise
356 """Main loop for children."""
359 # Re-seed random module
361 # urandom only exists in Python >= 2.4
366 pass
367 # Have doubts about this. random.seed will just hash the string
372 # Wait for any activity on the main socket or parent socket.
376 # If there's any activity on the parent socket, it
377 # means the parent wants us to die or has died itself.
378 # Either way, exit.
380 return
382 # Otherwise, there's activity on the main socket...
387 # Or maybe not.
388 continue
389 raise
393 # Check if this client is allowed.
396 continue
398 # Notify parent we're no longer available.
401 # Do the job.
404 # If we've serviced the maximum number of requests, exit.
408 break
410 # Tell parent we're free again.
414 # Signal handlers
424 # Do nothing (breaks us out of select and allows us to reap children).
425 pass
449 """Restores previous signal handlers."""
