From 482d0bcef2ab01c98db388f88d650b1d1d35e745 Mon Sep 17 00:00:00 2001 From: Robey Pointer Date: Tue, 31 Oct 2006 14:37:47 -0800 Subject: [PATCH] [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. --- paramiko/packet.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/paramiko/packet.py b/paramiko/packet.py index 60ee3d9..d43150d 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):