Browse code

Fixes #960 - Do a retry if exc has errno but errno is None. Python3 support.

Since py 3, there are new "OS-exception" including RemoteDisconnected.

Sadly, these exception are oserror and are supposed to have an errno
field, but if they are raised by some parts of cpython will not have any
value for errno.

That is the case for RemoteDisconnected raised by httlib instead of
BadStatusLine previously.

Florent Viard authored on 2018/06/04 08:38:31
Showing 1 changed files
... ...
@@ -1272,9 +1272,15 @@ class S3(object):
1272 1272
             ConnMan.put(conn)
1273 1273
         except (IOError, Exception) as e:
1274 1274
             debug("Response:\n" + pprint.pformat(response))
1275
-            if ((hasattr(e, 'errno') and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1276
-               or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)) and not isinstance(e, SocketTimeoutException):
1275
+            if ((hasattr(e, 'errno') and e.errno
1276
+                 and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1277
+                or "[Errno 104]" in str(e)
1278
+                or "[Errno 32]" in str(e)
1279
+               ) and not isinstance(e, SocketTimeoutException):
1277 1280
                 raise
1281
+            # When the connection is broken, BadStatusLine is raised with py2
1282
+            # and RemoteDisconnected is raised by py3 with a trap:
1283
+            # RemoteDisconnected has an errno field with a None value.
1278 1284
             if conn:
1279 1285
                 # close the connection and re-establish
1280 1286
                 conn.counter = ConnMan.conn_max_counter
... ...
@@ -1474,8 +1480,10 @@ class S3(object):
1474 1474
                 progress.done("failed")
1475 1475
             if retries:
1476 1476
                 known_error = False
1477
-                if ((hasattr(e, 'errno') and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1478
-                   or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)) and not isinstance(e, SocketTimeoutException):
1477
+                if ((hasattr(e, 'errno') and e.errno
1478
+                     and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1479
+                    or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)
1480
+                   ) and not isinstance(e, SocketTimeoutException):
1479 1481
                     # We have to detect these errors by looking at the error string
1480 1482
                     # Connection reset by peer and Broken pipe
1481 1483
                     # The server broke the connection early with an error like
... ...
@@ -1659,8 +1667,10 @@ class S3(object):
1659 1659
         except (IOError, Exception) as e:
1660 1660
             if self.config.progress_meter:
1661 1661
                 progress.done("failed")
1662
-            if ((hasattr(e, 'errno') and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1663
-               or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)) and not isinstance(e, SocketTimeoutException):
1662
+            if ((hasattr(e, 'errno') and e.errno and
1663
+                 e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1664
+                or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)
1665
+               ) and not isinstance(e, SocketTimeoutException):
1664 1666
                 raise
1665 1667
             if conn:
1666 1668
                 # close the connection and re-establish
... ...
@@ -1753,8 +1763,10 @@ class S3(object):
1753 1753
         except (IOError, Exception) as e:
1754 1754
             if self.config.progress_meter:
1755 1755
                 progress.done("failed")
1756
-            if ((hasattr(e, 'errno') and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1757
-               or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)) and not isinstance(e, SocketTimeoutException):
1756
+            if ((hasattr(e, 'errno') and e.errno
1757
+                 and e.errno not in (errno.EPIPE, errno.ECONNRESET, errno.ETIMEDOUT))
1758
+                or "[Errno 104]" in str(e) or "[Errno 32]" in str(e)
1759
+               ) and not isinstance(e, SocketTimeoutException):
1758 1760
                 raise
1759 1761
             # close the connection and re-establish
1760 1762
             conn.counter = ConnMan.conn_max_counter