[Python-checkins] cpython (3.5): Issue #26402: Fix XML-RPC client retrying after server disconnection

martin.panter python-checkins at python.org
Thu Feb 25 07:16:42 EST 2016


https://hg.python.org/cpython/rev/d668b5595534
changeset:   100331:d668b5595534
branch:      3.5
parent:      100328:baec3e2e1b1f
user:        Martin Panter <vadmium+py at gmail.com>
date:        Thu Feb 25 11:53:40 2016 +0000
summary:
  Issue #26402: Fix XML-RPC client retrying after server disconnection

This is a regression introduced in 3.5 by revision eba80326ba53. Fix by Jelte
Fennema, test case by me.

files:
  Lib/test/test_xmlrpc.py |  37 +++++++++++++++++++++++++++++
  Lib/xmlrpc/client.py    |   6 ++--
  Misc/NEWS               |   4 +++
  3 files changed, 44 insertions(+), 3 deletions(-)


diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py
--- a/Lib/test/test_xmlrpc.py
+++ b/Lib/test/test_xmlrpc.py
@@ -7,6 +7,7 @@
 import xmlrpc.client as xmlrpclib
 import xmlrpc.server
 import http.client
+import http, http.server
 import socket
 import os
 import re
@@ -244,6 +245,42 @@
         except OSError:
             self.assertTrue(has_ssl)
 
+    @unittest.skipUnless(threading, "Threading required for this test.")
+    def test_keepalive_disconnect(self):
+        class RequestHandler(http.server.BaseHTTPRequestHandler):
+            protocol_version = "HTTP/1.1"
+            handled = False
+
+            def do_POST(self):
+                length = int(self.headers.get("Content-Length"))
+                self.rfile.read(length)
+                if self.handled:
+                    self.close_connection = True
+                    return
+                response = xmlrpclib.dumps((5,), methodresponse=True)
+                response = response.encode()
+                self.send_response(http.HTTPStatus.OK)
+                self.send_header("Content-Length", len(response))
+                self.end_headers()
+                self.wfile.write(response)
+                self.handled = True
+                self.close_connection = False
+
+        def run_server():
+            server.socket.settimeout(float(1))  # Don't hang if client fails
+            server.handle_request()  # First request and attempt at second
+            server.handle_request()  # Retried second request
+
+        server = http.server.HTTPServer((support.HOST, 0), RequestHandler)
+        self.addCleanup(server.server_close)
+        thread = threading.Thread(target=run_server)
+        thread.start()
+        self.addCleanup(thread.join)
+        url = "http://{}:{}/".format(*server.server_address)
+        with xmlrpclib.ServerProxy(url) as p:
+            self.assertEqual(p.method(), 5)
+            self.assertEqual(p.method(), 5)
+
 class HelperTestCase(unittest.TestCase):
     def test_escape(self):
         self.assertEqual(xmlrpclib.escape("a&b"), "a&b")
diff --git a/Lib/xmlrpc/client.py b/Lib/xmlrpc/client.py
--- a/Lib/xmlrpc/client.py
+++ b/Lib/xmlrpc/client.py
@@ -1129,13 +1129,13 @@
         for i in (0, 1):
             try:
                 return self.single_request(host, handler, request_body, verbose)
+            except http.client.RemoteDisconnected:
+                if i:
+                    raise
             except OSError as e:
                 if i or e.errno not in (errno.ECONNRESET, errno.ECONNABORTED,
                                         errno.EPIPE):
                     raise
-            except http.client.RemoteDisconnected:
-                if i:
-                    raise
 
     def single_request(self, host, handler, request_body, verbose=False):
         # issue XML-RPC request
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -79,6 +79,10 @@
 Library
 -------
 
+- Issue #26402: Fix XML-RPC client to retry when the server shuts down a
+  persistent connection.  This was a regression related to the new
+  http.client.RemoteDisconnected exception in 3.5.0a4.
+
 - Issue #25913: Leading ``<~`` is optional now in base64.a85decode() with
   adobe=True.  Patch by Swati Jaiswal.
 

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list