Issue #26404: Add context manager to socketserver, by Aviv Palivoda
diff --git a/Doc/library/http.server.rst b/Doc/library/http.server.rst
index 0bde35b..7ab249a 100644
--- a/Doc/library/http.server.rst
+++ b/Doc/library/http.server.rst
@@ -375,10 +375,9 @@
 
    Handler = http.server.SimpleHTTPRequestHandler
 
-   httpd = socketserver.TCPServer(("", PORT), Handler)
-
-   print("serving at port", PORT)
-   httpd.serve_forever()
+   with socketserver.TCPServer(("", PORT), Handler) as httpd:
+       print("serving at port", PORT)
+       httpd.serve_forever()
 
 .. _http-server-cli:
 
diff --git a/Doc/library/socketserver.rst b/Doc/library/socketserver.rst
index aaaa61e..e148d30 100644
--- a/Doc/library/socketserver.rst
+++ b/Doc/library/socketserver.rst
@@ -52,11 +52,12 @@
 overriding its :meth:`~BaseRequestHandler.handle` method;
 this method will process incoming
 requests.  Second, you must instantiate one of the server classes, passing it
-the server's address and the request handler class.  Then call the
+the server's address and the request handler class. It is recommended to use
+the server in a :keyword:`with` statement. Then call the
 :meth:`~BaseServer.handle_request` or
 :meth:`~BaseServer.serve_forever` method of the server object to
 process one or many requests.  Finally, call :meth:`~BaseServer.server_close`
-to close the socket.
+to close the socket (unless you used a :keyword:`with` statement).
 
 When inheriting from :class:`ThreadingMixIn` for threaded connection behavior,
 you should explicitly declare how you want your threads to behave on an abrupt
@@ -353,6 +354,11 @@
       default implementation always returns :const:`True`.
 
 
+   .. versionchanged:: 3.6
+      Support for the :term:`context manager` protocol was added.  Exiting the
+      context manager is equivalent to calling :meth:`server_close`.
+
+
 Request Handler Objects
 -----------------------
 
@@ -433,11 +439,10 @@
        HOST, PORT = "localhost", 9999
 
        # Create the server, binding to localhost on port 9999
-       server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
-
-       # Activate the server; this will keep running until you
-       # interrupt the program with Ctrl-C
-       server.serve_forever()
+       with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
+           # Activate the server; this will keep running until you
+           # interrupt the program with Ctrl-C
+           server.serve_forever()
 
 An alternative request handler class that makes use of streams (file-like
 objects that simplify communication by providing the standard file interface)::
@@ -529,8 +534,8 @@
 
    if __name__ == "__main__":
        HOST, PORT = "localhost", 9999
-       server = socketserver.UDPServer((HOST, PORT), MyUDPHandler)
-       server.serve_forever()
+       with socketserver.UDPServer((HOST, PORT), MyUDPHandler) as server:
+           server.serve_forever()
 
 This is the client side::
 
@@ -592,22 +597,22 @@
        HOST, PORT = "localhost", 0
 
        server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
-       ip, port = server.server_address
+       with server:
+           ip, port = server.server_address
 
-       # Start a thread with the server -- that thread will then start one
-       # more thread for each request
-       server_thread = threading.Thread(target=server.serve_forever)
-       # Exit the server thread when the main thread terminates
-       server_thread.daemon = True
-       server_thread.start()
-       print("Server loop running in thread:", server_thread.name)
+           # Start a thread with the server -- that thread will then start one
+           # more thread for each request
+           server_thread = threading.Thread(target=server.serve_forever)
+           # Exit the server thread when the main thread terminates
+           server_thread.daemon = True
+           server_thread.start()
+           print("Server loop running in thread:", server_thread.name)
 
-       client(ip, port, "Hello World 1")
-       client(ip, port, "Hello World 2")
-       client(ip, port, "Hello World 3")
+           client(ip, port, "Hello World 1")
+           client(ip, port, "Hello World 2")
+           client(ip, port, "Hello World 3")
 
-       server.shutdown()
-       server.server_close()
+           server.shutdown()
 
 
 The output of the example should look something like this::
diff --git a/Doc/library/wsgiref.rst b/Doc/library/wsgiref.rst
index 71607d6..8d62885 100644
--- a/Doc/library/wsgiref.rst
+++ b/Doc/library/wsgiref.rst
@@ -131,9 +131,9 @@
                  for key, value in environ.items()]
           return ret
 
-      httpd = make_server('', 8000, simple_app)
-      print("Serving on port 8000...")
-      httpd.serve_forever()
+      with make_server('', 8000, simple_app) as httpd:
+          print("Serving on port 8000...")
+          httpd.serve_forever()
 
 
 In addition to the environment functions above, the :mod:`wsgiref.util` module
@@ -283,14 +283,14 @@
 
       from wsgiref.simple_server import make_server, demo_app
 
-      httpd = make_server('', 8000, demo_app)
-      print("Serving HTTP on port 8000...")
+      with make_server('', 8000, demo_app) as httpd:
+          print("Serving HTTP on port 8000...")
 
-      # Respond to requests until process is killed
-      httpd.serve_forever()
+          # Respond to requests until process is killed
+          httpd.serve_forever()
 
-      # Alternative: serve one request, then exit
-      httpd.handle_request()
+          # Alternative: serve one request, then exit
+          httpd.handle_request()
 
 
 .. function:: demo_app(environ, start_response)
@@ -430,9 +430,9 @@
       # This is the application wrapped in a validator
       validator_app = validator(simple_app)
 
-      httpd = make_server('', 8000, validator_app)
-      print("Listening on port 8000....")
-      httpd.serve_forever()
+      with make_server('', 8000, validator_app) as httpd:
+          print("Listening on port 8000....")
+          httpd.serve_forever()
 
 
 :mod:`wsgiref.handlers` -- server/gateway base classes
@@ -769,8 +769,8 @@
        # The returned object is going to be printed
        return [b"Hello World"]
 
-   httpd = make_server('', 8000, hello_world_app)
-   print("Serving on port 8000...")
+   with make_server('', 8000, hello_world_app) as httpd:
+       print("Serving on port 8000...")
 
-   # Serve until process is killed
-   httpd.serve_forever()
+       # Serve until process is killed
+       httpd.serve_forever()
diff --git a/Doc/library/xmlrpc.server.rst b/Doc/library/xmlrpc.server.rst
index 680db41..ca80aab 100644
--- a/Doc/library/xmlrpc.server.rst
+++ b/Doc/library/xmlrpc.server.rst
@@ -147,29 +147,29 @@
        rpc_paths = ('/RPC2',)
 
    # Create server
-   server = SimpleXMLRPCServer(("localhost", 8000),
-                               requestHandler=RequestHandler)
-   server.register_introspection_functions()
+   with SimpleXMLRPCServer(("localhost", 8000),
+                           requestHandler=RequestHandler) as server:
+       server.register_introspection_functions()
 
-   # Register pow() function; this will use the value of
-   # pow.__name__ as the name, which is just 'pow'.
-   server.register_function(pow)
+       # Register pow() function; this will use the value of
+       # pow.__name__ as the name, which is just 'pow'.
+       server.register_function(pow)
 
-   # Register a function under a different name
-   def adder_function(x,y):
-       return x + y
-   server.register_function(adder_function, 'add')
+       # Register a function under a different name
+       def adder_function(x,y):
+           return x + y
+       server.register_function(adder_function, 'add')
 
-   # Register an instance; all the methods of the instance are
-   # published as XML-RPC methods (in this case, just 'mul').
-   class MyFuncs:
-       def mul(self, x, y):
-           return x * y
+       # Register an instance; all the methods of the instance are
+       # published as XML-RPC methods (in this case, just 'mul').
+       class MyFuncs:
+           def mul(self, x, y):
+               return x * y
 
-   server.register_instance(MyFuncs())
+       server.register_instance(MyFuncs())
 
-   # Run the server's main loop
-   server.serve_forever()
+       # Run the server's main loop
+       server.serve_forever()
 
 The following client code will call the methods made available by the preceding
 server::
@@ -206,18 +206,17 @@
             def getCurrentTime():
                 return datetime.datetime.now()
 
-    server = SimpleXMLRPCServer(("localhost", 8000))
-    server.register_function(pow)
-    server.register_function(lambda x,y: x+y, 'add')
-    server.register_instance(ExampleService(), allow_dotted_names=True)
-    server.register_multicall_functions()
-    print('Serving XML-RPC on localhost port 8000')
-    try:
-        server.serve_forever()
-    except KeyboardInterrupt:
-        print("\nKeyboard interrupt received, exiting.")
-        server.server_close()
-        sys.exit(0)
+    with SimpleXMLRPCServer(("localhost", 8000)) as server:
+        server.register_function(pow)
+        server.register_function(lambda x,y: x+y, 'add')
+        server.register_instance(ExampleService(), allow_dotted_names=True)
+        server.register_multicall_functions()
+        print('Serving XML-RPC on localhost port 8000')
+        try:
+            server.serve_forever()
+        except KeyboardInterrupt:
+            print("\nKeyboard interrupt received, exiting.")
+            sys.exit(0)
 
 This ExampleService demo can be invoked from the command line::