diff options
author | Jeff Forcier <jeff@bitprophet.org> | 2014-02-12 17:16:34 -0800 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2014-02-12 17:16:34 -0800 |
commit | 58489c893e3f62947ee8235c2a07fc5465949aeb (patch) | |
tree | 3819f0d3c97d4e6d66c9e370f6245c152058313b | |
parent | 5b6059c4bd1b75121023b50003f5191345ef789c (diff) |
Potentially horrible attempt at manual subprocess-read timeouts
-rw-r--r-- | paramiko/proxy.py | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/paramiko/proxy.py b/paramiko/proxy.py index 218b76e2..abdd157c 100644 --- a/paramiko/proxy.py +++ b/paramiko/proxy.py @@ -20,10 +20,13 @@ L{ProxyCommand}. """ +from datetime import datetime import os from shlex import split as shlsplit import signal from subprocess import Popen, PIPE +from select import select +import socket from paramiko.ssh_exception import ProxyCommandFailure @@ -48,6 +51,7 @@ class ProxyCommand(object): """ self.cmd = shlsplit(command_line) self.process = Popen(self.cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) + self.timeout = None def send(self, content): """ @@ -78,7 +82,25 @@ class ProxyCommand(object): @rtype: int """ try: - return os.read(self.process.stdout.fileno(), size) + start = datetime.now() + read = [] + while len(read) < size: + if self.timeout is not None: + elapsed = (datetime.now() - start).microseconds + timeout = self.timeout * 1000 * 1000 # to microseconds + # Unsure why the 'default' timeout is too short here - + # causes us to raise before e.g. the SSH banner is read, + # probably generally awful for slow connections. + # Try inflating it some. + timeout = timeout * 2 + if elapsed >= timeout: + raise socket.timeout() + r, w, x = select([self.process.stdout], [], [], 0.0) + if r and r[0] == self.process.stdout: + b = os.read(self.process.stdout.fileno(), 1) + read.append(b) + result = ''.join(read) + return result except IOError, e: raise BadProxyCommand(' '.join(self.cmd), e.strerror) @@ -86,6 +108,4 @@ class ProxyCommand(object): os.kill(self.process.pid, signal.SIGTERM) def settimeout(self, timeout): - # Timeouts are meaningless for this implementation, but are part of the - # spec, so must be present. - pass + self.timeout = timeout |