Kaydet (Commit) c71fae5a authored tarafından Kristján Valur Jónsson's avatar Kristján Valur Jónsson

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.
üst e93eee7d
...@@ -168,6 +168,7 @@ class BaseServer: ...@@ -168,6 +168,7 @@ class BaseServer:
- verify_request(request, client_address) - verify_request(request, client_address)
- server_close() - server_close()
- process_request(request, client_address) - process_request(request, client_address)
- shutdown_request(request)
- close_request(request) - close_request(request)
- handle_error() - handle_error()
...@@ -281,7 +282,7 @@ class BaseServer: ...@@ -281,7 +282,7 @@ class BaseServer:
self.process_request(request, client_address) self.process_request(request, client_address)
except: except:
self.handle_error(request, client_address) self.handle_error(request, client_address)
self.close_request(request) self.shutdown_request(request)
def handle_timeout(self): def handle_timeout(self):
"""Called if no new request arrives within self.timeout. """Called if no new request arrives within self.timeout.
...@@ -305,7 +306,7 @@ class BaseServer: ...@@ -305,7 +306,7 @@ class BaseServer:
""" """
self.finish_request(request, client_address) self.finish_request(request, client_address)
self.close_request(request) self.shutdown_request(request)
def server_close(self): def server_close(self):
"""Called to clean-up the server. """Called to clean-up the server.
...@@ -319,6 +320,10 @@ class BaseServer: ...@@ -319,6 +320,10 @@ class BaseServer:
"""Finish one request by instantiating RequestHandlerClass.""" """Finish one request by instantiating RequestHandlerClass."""
self.RequestHandlerClass(request, client_address, self) 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): def close_request(self, request):
"""Called to clean up an individual request.""" """Called to clean up an individual request."""
pass pass
...@@ -359,6 +364,7 @@ class TCPServer(BaseServer): ...@@ -359,6 +364,7 @@ class TCPServer(BaseServer):
- handle_timeout() - handle_timeout()
- verify_request(request, client_address) - verify_request(request, client_address)
- process_request(request, client_address) - process_request(request, client_address)
- shutdown_request(request)
- close_request(request) - close_request(request)
- handle_error() - handle_error()
...@@ -443,14 +449,18 @@ class TCPServer(BaseServer): ...@@ -443,14 +449,18 @@ class TCPServer(BaseServer):
""" """
return self.socket.accept() return self.socket.accept()
def close_request(self, request): def shutdown_request(self, request):
"""Called to clean up an individual request.""" """Called to shutdown and close an individual request."""
try: try:
#explicitly shutdown. socket.close() merely releases #explicitly shutdown. socket.close() merely releases
#the socket and waits for GC to perform the actual close. #the socket and waits for GC to perform the actual close.
request.shutdown(socket.SHUT_WR) request.shutdown(socket.SHUT_WR)
except socket.error: except socket.error:
pass #some platforms may raise ENOTCONN here 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() request.close()
...@@ -472,6 +482,10 @@ class UDPServer(TCPServer): ...@@ -472,6 +482,10 @@ class UDPServer(TCPServer):
# No need to call listen() for UDP. # No need to call listen() for UDP.
pass pass
def shutdown_request(self, request):
# No need to shutdown anything.
self.close_request(request)
def close_request(self, request): def close_request(self, request):
# No need to close anything. # No need to close anything.
pass pass
...@@ -532,19 +546,19 @@ class ForkingMixIn: ...@@ -532,19 +546,19 @@ class ForkingMixIn:
if self.active_children is None: if self.active_children is None:
self.active_children = [] self.active_children = []
self.active_children.append(pid) self.active_children.append(pid)
request.close() #close socket handle in parent process self.close_request(request) #close handle in parent process
return return
else: else:
# Child process. # Child process.
# This must never return, hence os._exit()! # This must never return, hence os._exit()!
try: try:
self.finish_request(request, client_address) self.finish_request(request, client_address)
self.close_request(request) self.shutdown_request(request)
os._exit(0) os._exit(0)
except: except:
try: try:
self.handle_error(request, client_address) self.handle_error(request, client_address)
self.close_request(request) self.shutdown_request(request)
finally: finally:
os._exit(1) os._exit(1)
...@@ -564,10 +578,10 @@ class ThreadingMixIn: ...@@ -564,10 +578,10 @@ class ThreadingMixIn:
""" """
try: try:
self.finish_request(request, client_address) self.finish_request(request, client_address)
self.close_request(request) self.shutdown_request(request)
except: except:
self.handle_error(request, client_address) self.handle_error(request, client_address)
self.close_request(request) self.shutdown_request(request)
def process_request(self, request, client_address): def process_request(self, request, client_address):
"""Start a new thread to process the request.""" """Start a new thread to process the request."""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment