diff options
author | Martin Panter <vadmium+py@gmail.com> | 2016-02-25 11:53:40 (GMT) |
---|---|---|
committer | Martin Panter <vadmium+py@gmail.com> | 2016-02-25 11:53:40 (GMT) |
commit | eae3336e425a718d6c17ee1247236a62080bac7f (patch) | |
tree | 144b7ec9f5b2a289b23a5f5c175e13947182a772 /Lib | |
parent | f828218d652fe8120d88cfefa52df5c2039cdf92 (diff) | |
download | cpython-eae3336e425a718d6c17ee1247236a62080bac7f.zip cpython-eae3336e425a718d6c17ee1247236a62080bac7f.tar.gz cpython-eae3336e425a718d6c17ee1247236a62080bac7f.tar.bz2 |
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.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_xmlrpc.py | 37 | ||||
-rw-r--r-- | Lib/xmlrpc/client.py | 6 |
2 files changed, 40 insertions, 3 deletions
diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index d142a15..831a5a5 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -7,6 +7,7 @@ from unittest import mock 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 @@ class XMLRPCTestCase(unittest.TestCase): 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 index bf42835..e7daa07 100644 --- a/Lib/xmlrpc/client.py +++ b/Lib/xmlrpc/client.py @@ -1129,13 +1129,13 @@ class Transport: 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 |