From a5b47cea768425d025bc29379da24d2ba2d379dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Valur=20J=C3=B3nsson?= Date: Tue, 7 Jul 2009 09:09:10 +0000 Subject: [PATCH] http://bugs.python.org/issue6382 added the shutdown_request() which can perform shutdown before calling close. This is needed for the ForkingMixIn because different close semantics are required for child and parent process. shutdown_request(), for TCP servers, calls socket.shutdown() and then calls close_request(). Therefore, this is not an backwards incompatible change, since subclasses that continue to override close_request() continue to work. --- Lib/socketserver.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Lib/socketserver.py b/Lib/socketserver.py index 37df2bab33c..dacec0376bd 100644 --- a/Lib/socketserver.py +++ b/Lib/socketserver.py @@ -168,6 +168,7 @@ class BaseServer: - verify_request(request, client_address) - server_close() - process_request(request, client_address) + - shutdown_request(request) - close_request(request) - handle_error() @@ -281,7 +282,7 @@ class BaseServer: self.process_request(request, client_address) except: self.handle_error(request, client_address) - self.close_request(request) + self.shutdown_request(request) def handle_timeout(self): """Called if no new request arrives within self.timeout. @@ -305,7 +306,7 @@ class BaseServer: """ self.finish_request(request, client_address) - self.close_request(request) + self.shutdown_request(request) def server_close(self): """Called to clean-up the server. @@ -319,6 +320,10 @@ class BaseServer: """Finish one request by instantiating RequestHandlerClass.""" self.RequestHandlerClass(request, client_address, self) + def shutdown_request(self, request): + """Called to shutdown and close an individual request.""" + self.close_request(request) + def close_request(self, request): """Called to clean up an individual request.""" pass @@ -359,6 +364,7 @@ class TCPServer(BaseServer): - handle_timeout() - verify_request(request, client_address) - process_request(request, client_address) + - shutdown_request(request) - close_request(request) - handle_error() @@ -443,14 +449,18 @@ class TCPServer(BaseServer): """ return self.socket.accept() - def close_request(self, request): - """Called to clean up an individual request.""" + def shutdown_request(self, request): + """Called to shutdown and close an individual request.""" try: #explicitly shutdown. socket.close() merely releases #the socket and waits for GC to perform the actual close. request.shutdown(socket.SHUT_WR) except socket.error: pass #some platforms may raise ENOTCONN here + self.close_request(request) + + def close_request(self, request): + """Called to clean up an individual request.""" request.close() @@ -472,6 +482,10 @@ class UDPServer(TCPServer): # No need to call listen() for UDP. pass + def shutdown_request(self, request): + # No need to shutdown anything. + self.close_request(request) + def close_request(self, request): # No need to close anything. pass @@ -539,10 +553,12 @@ class ForkingMixIn: # This must never return, hence os._exit()! try: self.finish_request(request, client_address) + self.shutdown_request(request) os._exit(0) except: try: self.handle_error(request, client_address) + self.shutdown_request(request) finally: os._exit(1) @@ -562,10 +578,10 @@ class ThreadingMixIn: """ try: self.finish_request(request, client_address) - self.close_request(request) + self.shutdown_request(request) except: self.handle_error(request, client_address) - self.close_request(request) + self.shutdown_request(request) def process_request(self, request, client_address): """Start a new thread to process the request."""