diff options
author | Robey Pointer <robey@lag.net> | 2007-10-28 20:03:44 -0700 |
---|---|---|
committer | Robey Pointer <robey@lag.net> | 2007-10-28 20:03:44 -0700 |
commit | e3d9b90ea1f25792e652a0809b37b52635243932 (patch) | |
tree | c6b99f4940f2ceec7941500839d860119d0609fb /paramiko/pipe.py | |
parent | 80b9e289cef4fc0939141ccf15751017a58a1637 (diff) | |
download | paramiko-e3d9b90ea1f25792e652a0809b37b52635243932.tar.gz |
[project @ robey@lag.net-20071029030344-9adfzb9ulfodtepu]
bug 157205: select() doesn't notify incoming stderr data, because stderr's
pipe isn't hooked up to the fileno() BufferedPipe. to fix, i added an "or"
pipe-event that can be triggered by either stdout or stderr, and hooked
them both up to fileno(). added a unit test for the bug and one for the
"or" pipe.
Diffstat (limited to 'paramiko/pipe.py')
-rw-r--r-- | paramiko/pipe.py | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/paramiko/pipe.py b/paramiko/pipe.py index d71ca167..1cfed2d0 100644 --- a/paramiko/pipe.py +++ b/paramiko/pipe.py @@ -19,6 +19,9 @@ """ Abstraction of a one-way pipe where the read end can be used in select(). Normally this is trivial, but Windows makes it nearly impossible. + +The pipe acts like an Event, which can be set or cleared. When set, the pipe +will trigger as readable in select(). """ import sys @@ -57,7 +60,7 @@ class PosixPipe (object): self._set = False def set (self): - if self._set: + if self._set or self._closed: return self._set = True os.write(self._wfd, '*') @@ -103,7 +106,7 @@ class WindowsPipe (object): self._set = False def set (self): - if self._set: + if self._set or self._closed: return self._set = True self._wsock.send('*') @@ -111,3 +114,34 @@ class WindowsPipe (object): def set_forever (self): self._forever = True self.set() + + +class OrPipe (object): + def __init__(self, pipe): + self._set = False + self._partner = None + self._pipe = pipe + + def set(self): + self._set = True + if not self._partner._set: + self._pipe.set() + + def clear(self): + self._set = False + if not self._partner._set: + self._pipe.clear() + + +def make_or_pipe(pipe): + """ + wraps a pipe into two pipe-like objects which are "or"d together to + affect the real pipe. if either returned pipe is set, the wrapped pipe + is set. when both are cleared, the wrapped pipe is cleared. + """ + p1 = OrPipe(pipe) + p2 = OrPipe(pipe) + p1._partner = p2 + p2._partner = p1 + return p1, p2 + |