summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMartin Panter <vadmium+py@gmail.com>2016-02-25 11:53:40 (GMT)
committerMartin Panter <vadmium+py@gmail.com>2016-02-25 11:53:40 (GMT)
commiteae3336e425a718d6c17ee1247236a62080bac7f (patch)
tree144b7ec9f5b2a289b23a5f5c175e13947182a772 /Lib
parentf828218d652fe8120d88cfefa52df5c2039cdf92 (diff)
downloadcpython-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.py37
-rw-r--r--Lib/xmlrpc/client.py6
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&amp;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