|
@@ -234,85 +234,6 @@ class ServerTests(object):
|
|
|
self.assertReposEqual(clone, self._source_repo)
|
|
|
|
|
|
|
|
|
-class ShutdownServerMixIn:
|
|
|
- """Mixin that allows serve_forever to be shut down.
|
|
|
-
|
|
|
- The methods in this mixin are backported from SocketServer.py in the Python
|
|
|
- 2.6.4 standard library. The mixin is unnecessary in 2.6 and later, when
|
|
|
- BaseServer supports the shutdown method directly.
|
|
|
- """
|
|
|
-
|
|
|
- def __init__(self):
|
|
|
- self.__is_shut_down = threading.Event()
|
|
|
- self.__serving = False
|
|
|
-
|
|
|
- def serve_forever(self, poll_interval=0.5):
|
|
|
- """Handle one request at a time until shutdown.
|
|
|
-
|
|
|
- Polls for shutdown every poll_interval seconds. Ignores
|
|
|
- self.timeout. If you need to do periodic tasks, do them in
|
|
|
- another thread.
|
|
|
- """
|
|
|
- self.__serving = True
|
|
|
- self.__is_shut_down.clear()
|
|
|
- while self.__serving:
|
|
|
- # XXX: Consider using another file descriptor or
|
|
|
- # connecting to the socket to wake this up instead of
|
|
|
- # polling. Polling reduces our responsiveness to a
|
|
|
- # shutdown request and wastes cpu at all other times.
|
|
|
- r, w, e = select.select([self], [], [], poll_interval)
|
|
|
- if r:
|
|
|
- self._handle_request_noblock()
|
|
|
- self.__is_shut_down.set()
|
|
|
-
|
|
|
- serve = serve_forever # override alias from TCPGitServer
|
|
|
-
|
|
|
- def shutdown(self):
|
|
|
- """Stops the serve_forever loop.
|
|
|
-
|
|
|
- Blocks until the loop has finished. This must be called while
|
|
|
- serve_forever() is running in another thread, or it will deadlock.
|
|
|
- """
|
|
|
- self.__serving = False
|
|
|
- self.__is_shut_down.wait()
|
|
|
-
|
|
|
- def handle_request(self):
|
|
|
- """Handle one request, possibly blocking.
|
|
|
-
|
|
|
- Respects self.timeout.
|
|
|
- """
|
|
|
- # Support people who used socket.settimeout() to escape
|
|
|
- # handle_request before self.timeout was available.
|
|
|
- timeout = self.socket.gettimeout()
|
|
|
- if timeout is None:
|
|
|
- timeout = self.timeout
|
|
|
- elif self.timeout is not None:
|
|
|
- timeout = min(timeout, self.timeout)
|
|
|
- fd_sets = select.select([self], [], [], timeout)
|
|
|
- if not fd_sets[0]:
|
|
|
- self.handle_timeout()
|
|
|
- return
|
|
|
- self._handle_request_noblock()
|
|
|
-
|
|
|
- def _handle_request_noblock(self):
|
|
|
- """Handle one request, without blocking.
|
|
|
-
|
|
|
- I assume that select.select has returned that the socket is
|
|
|
- readable before this function was called, so there should be
|
|
|
- no risk of blocking in get_request().
|
|
|
- """
|
|
|
- try:
|
|
|
- request, client_address = self.get_request()
|
|
|
- except socket.error:
|
|
|
- return
|
|
|
- if self.verify_request(request, client_address):
|
|
|
- try:
|
|
|
- self.process_request(request, client_address)
|
|
|
- except:
|
|
|
- self.handle_error(request, client_address)
|
|
|
- self.close_request(request)
|
|
|
-
|
|
|
-
|
|
|
# TODO(dborowitz): Come up with a better way of testing various permutations of
|
|
|
# capabilities. The only reason it is the way it is now is that side-band-64k
|
|
|
# was only recently introduced into git-receive-pack.
|