mirror of https://github.com/python/cpython
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.
This commit is contained in:
parent
783f86ecb1
commit
a5b47cea76
|
@ -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:
|
||||||
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:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
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:
|
||||||
"""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):
|
||||||
- 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):
|
||||||
"""
|
"""
|
||||||
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):
|
||||||
# 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
|
||||||
|
@ -539,10 +553,12 @@ class ForkingMixIn:
|
||||||
# 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.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.shutdown_request(request)
|
||||||
finally:
|
finally:
|
||||||
os._exit(1)
|
os._exit(1)
|
||||||
|
|
||||||
|
@ -562,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."""
|
||||||
|
|
Loading…
Reference in New Issue