summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--paramiko/packet.py24
1 files changed, 22 insertions, 2 deletions
diff --git a/paramiko/packet.py b/paramiko/packet.py
index 60ee3d99..d43150d9 100644
--- a/paramiko/packet.py
+++ b/paramiko/packet.py
@@ -20,6 +20,7 @@
Packetizer.
"""
+import errno
import select
import socket
import struct
@@ -201,6 +202,7 @@ class Packetizer (object):
if PY22:
return self._py22_read_all(n, out)
while n > 0:
+ got_timeout = False
try:
x = self.__socket.recv(n)
if len(x) == 0:
@@ -208,6 +210,16 @@ class Packetizer (object):
out += x
n -= len(x)
except socket.timeout:
+ got_timeout = True
+ except socket.error, e:
+ # on Linux, sometimes instead of socket.timeout, we get
+ # EAGAIN. this is a bug in recent (> 2.6.9) kernels but
+ # we need to work around it.
+ if (type(e.args) is tuple) and (len(e.args) > 0) and (e.args[0] == errno.EAGAIN):
+ got_timeout = True
+ else:
+ raise
+ if got_timeout:
if self.__closed:
raise EOFError()
if check_rekey and (len(out) == 0) and self.__need_rekey:
@@ -218,15 +230,23 @@ class Packetizer (object):
def write_all(self, out):
self.__keepalive_last = time.time()
while len(out) > 0:
+ got_timeout = False
try:
n = self.__socket.send(out)
except socket.timeout:
- n = 0
- if self.__closed:
+ got_timeout = True
+ except socket.error, e:
+ if (type(e.args) is tuple) and (len(e.args) > 0) and (e.args[0] == errno.EAGAIN):
+ got_timeout = True
+ else:
n = -1
except Exception:
# could be: (32, 'Broken pipe')
n = -1
+ if got_timeout:
+ n = 0
+ if self.__closed:
+ n = -1
if n < 0:
raise EOFError()
if n == len(out):