summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobey Pointer <robey@lag.net>2006-10-31 14:37:47 -0800
committerRobey Pointer <robey@lag.net>2006-10-31 14:37:47 -0800
commit482d0bcef2ab01c98db388f88d650b1d1d35e745 (patch)
tree7eba62cafbad75661ff4c9638c733acd9b2e78c6
parent4628a53acffa07af2a2d1b34fac83e196211c5fe (diff)
[project @ robey@lag.net-20061031223747-9fda3f2c1112c5dc]
(bug 69222) on some recent linux kernels, a socket can return "readable" from select, but a subsequent read() will return EAGAIN. this is against the contract of select(), so python's socketmodule doesn't catch it or handle it. therefore, we need to. EAGAIN should now be treated the same as a socket timeout.
-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):