summaryrefslogtreecommitdiff
path: root/Lib/SocketServer.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/SocketServer.py')
-rw-r--r--Lib/SocketServer.py49
1 files changed, 41 insertions, 8 deletions
diff --git a/Lib/SocketServer.py b/Lib/SocketServer.py
index 7040738e76..f1fd78b86b 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()
@@ -283,7 +284,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.
@@ -307,7 +308,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.
@@ -321,6 +322,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
@@ -361,6 +366,7 @@ class TCPServer(BaseServer):
- handle_timeout()
- verify_request(request, client_address)
- process_request(request, client_address)
+ - shutdown_request(request)
- close_request(request)
- handle_error()
@@ -445,6 +451,16 @@ class TCPServer(BaseServer):
"""
return self.socket.accept()
+ 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()
@@ -468,6 +484,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
@@ -528,17 +548,19 @@ class ForkingMixIn:
if self.active_children is None:
self.active_children = []
self.active_children.append(pid)
- self.close_request(request)
+ self.close_request(request) #close handle in parent process
return
else:
# Child process.
# 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)
@@ -558,10 +580,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."""
@@ -612,12 +634,11 @@ class BaseRequestHandler:
self.request = request
self.client_address = client_address
self.server = server
+ self.setup()
try:
- self.setup()
self.handle()
- self.finish()
finally:
- sys.exc_traceback = None # Help garbage collection
+ self.finish()
def setup(self):
pass
@@ -651,8 +672,20 @@ class StreamRequestHandler(BaseRequestHandler):
rbufsize = -1
wbufsize = 0
+ # A timeout to apply to the request socket, if not None.
+ timeout = None
+
+ # Disable nagle algorithm for this socket, if True.
+ # Use only when wbufsize != 0, to avoid small packets.
+ disable_nagle_algorithm = False
+
def setup(self):
self.connection = self.request
+ if self.timeout is not None:
+ self.connection.settimeout(self.timeout)
+ if self.disable_nagle_algorithm:
+ self.connection.setsockopt(socket.IPPROTO_TCP,
+ socket.TCP_NODELAY, True)
self.rfile = self.connection.makefile('rb', self.rbufsize)
self.wfile = self.connection.makefile('wb', self.wbufsize)