# HG changeset patch # Parent 0cfac9efd895f8b0468ab72b0f07716ee21b649a 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. diff -r 0cfac9efd895 Lib/test/test_xmlrpc.py --- a/Lib/test/test_xmlrpc.py Sun Feb 21 22:00:12 2016 +0200 +++ b/Lib/test/test_xmlrpc.py Mon Feb 22 08:22:04 2016 +0000 @@ -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 -r 0cfac9efd895 Lib/xmlrpc/client.py --- a/Lib/xmlrpc/client.py Sun Feb 21 22:00:12 2016 +0200 +++ b/Lib/xmlrpc/client.py Mon Feb 22 08:22:04 2016 +0000 @@ -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 -r 0cfac9efd895 Misc/NEWS --- a/Misc/NEWS Sun Feb 21 22:00:12 2016 +0200 +++ b/Misc/NEWS Mon Feb 22 08:22:04 2016 +0000 @@ -76,6 +76,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 #26186: Remove an invalid type check in importlib.util.LazyLoader. - Issue #26367: importlib.__import__() raises SystemError like