reorder the closing of the pipe in Channel.close() to make sure it happens even when the channel is closed by the remote host first
This commit is contained in:
Robey Pointer 2006-11-20 11:21:37 -08:00
parent b956cc4831
commit 48bb10694b
3 changed files with 29 additions and 16 deletions

View File

@ -86,7 +86,7 @@ class Channel (object):
self.status_event = threading.Event() self.status_event = threading.Event()
self.name = str(chanid) self.name = str(chanid)
self.logger = util.get_logger('paramiko.chan.' + str(chanid)) self.logger = util.get_logger('paramiko.chan.' + str(chanid))
self.pipe = None self._pipe = None
self.event = threading.Event() self.event = threading.Event()
self.combine_stderr = False self.combine_stderr = False
self.exit_status = -1 self.exit_status = -1
@ -457,15 +457,17 @@ class Channel (object):
""" """
self.lock.acquire() self.lock.acquire()
try: try:
# only close the pipe when the user explicitly closes the channel.
# otherwise they will get unpleasant surprises. (and do it before
# checking self.closed, since the remote host may have already
# closed the connection.)
if self._pipe is not None:
self._pipe.close()
self._pipe = None
if not self.active or self.closed: if not self.active or self.closed:
return return
msgs = self._close_internal() msgs = self._close_internal()
# only close the pipe when the user explicitly closes the channel.
# otherwise they will get unpleasant surprises.
if self.pipe is not None:
self.pipe.close()
self.pipe = None
finally: finally:
self.lock.release() self.lock.release()
for m in msgs: for m in msgs:
@ -732,12 +734,12 @@ class Channel (object):
""" """
self.lock.acquire() self.lock.acquire()
try: try:
if self.pipe is not None: if self._pipe is not None:
return self.pipe.fileno() return self._pipe.fileno()
# create the pipe and feed in any existing data # create the pipe and feed in any existing data
self.pipe = pipe.make_pipe() self._pipe = pipe.make_pipe()
self.in_buffer.set_event(self.pipe) self.in_buffer.set_event(self._pipe)
return self.pipe.fileno() return self._pipe.fileno()
finally: finally:
self.lock.release() self.lock.release()
@ -926,8 +928,8 @@ class Channel (object):
self.eof_received = True self.eof_received = True
self.in_buffer.close() self.in_buffer.close()
self.in_stderr_buffer.close() self.in_stderr_buffer.close()
if self.pipe is not None: if self._pipe is not None:
self.pipe.set_forever() self._pipe.set_forever()
finally: finally:
self.lock.release() self.lock.release()
self._log(DEBUG, 'EOF received') self._log(DEBUG, 'EOF received')
@ -968,8 +970,8 @@ class Channel (object):
self.in_buffer.close() self.in_buffer.close()
self.in_stderr_buffer.close() self.in_stderr_buffer.close()
self.out_buffer_cv.notifyAll() self.out_buffer_cv.notifyAll()
if self.pipe is not None: if self._pipe is not None:
self.pipe.set_forever() self._pipe.set_forever()
def _send_eof(self): def _send_eof(self):
# you are holding the lock. # you are holding the lock.

View File

@ -39,10 +39,13 @@ class PosixPipe (object):
self._rfd, self._wfd = os.pipe() self._rfd, self._wfd = os.pipe()
self._set = False self._set = False
self._forever = False self._forever = False
self._closed = False
def close (self): def close (self):
os.close(self._rfd) os.close(self._rfd)
os.close(self._wfd) os.close(self._wfd)
# used for unit tests:
self._closed = True
def fileno (self): def fileno (self):
return self._rfd return self._rfd
@ -82,10 +85,13 @@ class WindowsPipe (object):
serv.close() serv.close()
self._set = False self._set = False
self._forever = False self._forever = False
self._closed = False
def close (self): def close (self):
self._rsock.close() self._rsock.close()
self._wsock.close() self._wsock.close()
# used for unit tests:
self._closed = True
def fileno (self): def fileno (self):
return self._rsock.fileno() return self._rsock.fileno()

View File

@ -538,7 +538,12 @@ class TransportTest (unittest.TestCase):
self.assertEquals([], e) self.assertEquals([], e)
self.assertEquals('', chan.recv(16)) self.assertEquals('', chan.recv(16))
# make sure the pipe is still open for now...
p = chan._pipe
self.assertEquals(False, p._closed)
chan.close() chan.close()
# ...and now is closed.
self.assertEquals(True, p._closed)
def test_G_renegotiate(self): def test_G_renegotiate(self):
""" """