# HG changeset patch # User Augie Fackler # Date 1377288982 14400 # Node ID d4a0055af149cdea20b3136b66cae8a24b2e2a98 # Parent 4694ccd5d994527d34a341c7c1ba4949aeafa499 httpclient: import 0d1b0a8bc549 to fix bug involving late-arriving RST after a response After a day of hunting this defect, I'm now unable to reproduce the bug without this patch applied. Regardless, this should fix the problem I was observing with wireshark. Hopefully this fixes any flakiness in the buildbot from http2. diff -r 4694ccd5d994 -r d4a0055af149 mercurial/httpclient/__init__.py --- a/mercurial/httpclient/__init__.py Fri Aug 23 13:28:18 2013 -0400 +++ b/mercurial/httpclient/__init__.py Fri Aug 23 16:16:22 2013 -0400 @@ -495,6 +495,10 @@ else: raise BadRequestData('body has no __len__() nor read()') + # If we're reusing the underlying socket, there are some + # conditions where we'll want to retry, so make a note of the + # state of self.sock + fresh_socket = self.sock is None self._connect() outgoing_headers = self._buildheaders( method, path, hdrs, self.http_version) @@ -640,6 +644,26 @@ # the whole request if response is None: response = self.response_class(self.sock, self.timeout, method) + if not fresh_socket: + if not response._select(): + # This means the response failed to get any response + # data at all, and in all probability the socket was + # closed before the server even saw our request. Try + # the request again on a fresh socket. + logging.debug('response._select() failed during request().' + ' Assuming request needs to be retried.') + self.sock = None + # Call this method explicitly to re-try the + # request. We don't use self.request() because + # some tools (notably Mercurial) expect to be able + # to subclass and redefine request(), and they + # don't have the same argspec as we do. + # + # TODO restructure sending of requests to avoid + # this recursion + return HTTPConnection.request( + self, method, path, body=body, headers=headers, + expect_continue=expect_continue) data_left = bool(outgoing_headers or body) if data_left: logger.info('stopped sending request early, '