Rev 3652: Fix bug #225020 by catching CURLE_SEND_ERROR error. in lp:~vila/bzr/225020-select-poll

Vincent Ladeuil v.ladeuil+lp at free.fr
Wed Aug 27 21:26:15 BST 2008


At lp:~vila/bzr/225020-select-poll

------------------------------------------------------------
revno: 3652
revision-id: v.ladeuil+lp at free.fr-20080827202611-8l16umo6ylc4rbnw
parent: pqm at pqm.ubuntu.com-20080827044137-4ox67ehr4bxtj7b0
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: 225020-select-poll
timestamp: Wed 2008-08-27 22:26:11 +0200
message:
  Fix bug #225020 by catching CURLE_SEND_ERROR error.
  
  * bzrlib/transport/http/_pycurl.py:
  (PyCurlTransport._post): There is a race condition between
  HTTP/1.0 servers refusing a POST request and the curl library
  trying to send the body request anyway. In rare occurrences, the
  connection is already closed.
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/transport/http/_pycurl.py pycurlhttp.py-20060110060940-4e2a705911af77a6
-------------- next part --------------
=== modified file 'NEWS'
--- a/NEWS	2008-08-25 17:49:41 +0000
+++ b/NEWS	2008-08-27 20:26:11 +0000
@@ -32,6 +32,10 @@
     * ``bzr rm`` is now aliased to ``bzr del`` for the convenience of svn
       users. (Robert Collins, #205416)
 
+    * Catch the infamous "select/poll returned error" which occurs when
+      pycurl try to send a body request to an HTTP/1.0 server which has
+      already refused to handle the request. (Vincent Ladeuil, #225020)
+
     * ``FTPTransport.stat()`` would return ``0000`` as the permission bits
       for the containing ``.bzr/`` directory (it does not implement
       permissions). This would cause us to set all subdirectories to

=== modified file 'bzrlib/transport/http/_pycurl.py'
--- a/bzrlib/transport/http/_pycurl.py	2008-05-18 13:59:54 +0000
+++ b/bzrlib/transport/http/_pycurl.py	2008-08-27 20:26:11 +0000
@@ -92,6 +92,7 @@
 CURLE_COULDNT_RESOLVE_PROXY = _get_pycurl_errcode('E_COULDNT_RESOLVE_PROXY', 5)
 CURLE_GOT_NOTHING = _get_pycurl_errcode('E_GOT_NOTHING', 52)
 CURLE_PARTIAL_FILE = _get_pycurl_errcode('E_PARTIAL_FILE', 18)
+CURLE_SEND_ERROR = _get_pycurl_errcode('E_SEND_ERROR', 55)
 
 
 class PyCurlTransport(HttpTransportBase):
@@ -254,18 +255,29 @@
         return msg
 
     def _post(self, body_bytes):
+        curl = self._get_curl()
+        abspath, data, header = self._setup_request(curl, '.bzr/smart')
+        curl.setopt(pycurl.POST, 1)
         fake_file = StringIO(body_bytes)
-        curl = self._get_curl()
-        # Other places that use the Curl object (returned by _get_curl)
-        # for GET requests explicitly set HTTPGET, so it should be safe to
-        # re-use the same object for both GETs and POSTs.
-        curl.setopt(pycurl.POST, 1)
         curl.setopt(pycurl.POSTFIELDSIZE, len(body_bytes))
         curl.setopt(pycurl.READFUNCTION, fake_file.read)
-        abspath, data, header = self._setup_request(curl, '.bzr/smart')
         # We override the Expect: header so that pycurl will send the POST
         # body immediately.
-        self._curl_perform(curl, header, ['Expect: '])
+        try:
+            self._curl_perform(curl, header, ['Expect: '])
+        except pycurl.error, e:
+            if e[0] == CURLE_SEND_ERROR:
+                # This has been observed when curl assumes a closed connection
+                # when talking to HTTP/1.0 servers, getting a 403, but trying
+                # to send the request body anyway. (see bug #225020)
+                code = curl.getinfo(pycurl.HTTP_CODE)
+                if code == 403:
+                    raise errors.InvalidHttpResponse(
+                        abspath,
+                        'Unexpected send error,'
+                        ' the server probably closed the connection')
+            # Re-raise otherwise
+            raise
         data.seek(0)
         code = curl.getinfo(pycurl.HTTP_CODE)
         msg = self._parse_headers(header)



More information about the bazaar-commits mailing list