[project @ Arch-1:robey@lag.net--2005-master-shake%paramiko--dev--1--patch-34]

fix a comment claiming that channels are closed automatically when GC'd (they aren't and can't be); don't close the pipe until the app explicitly calls close(); signal EOF via the pipe
This commit is contained in:
Robey Pointer 2005-07-14 02:17:38 +00:00
parent 93f3cae64f
commit f565576321
1 changed files with 38 additions and 21 deletions

View File

@ -87,7 +87,7 @@ class Channel (object):
self.event = threading.Event() self.event = threading.Event()
self.combine_stderr = False self.combine_stderr = False
self.exit_status = -1 self.exit_status = -1
def __repr__(self): def __repr__(self):
""" """
Return a string representation of this object, for debugging. Return a string representation of this object, for debugging.
@ -454,24 +454,25 @@ class Channel (object):
""" """
Close the channel. All future read/write operations on the channel Close the channel. All future read/write operations on the channel
will fail. The remote end will receive no more data (after queued data will fail. The remote end will receive no more data (after queued data
is flushed). Channels are automatically closed when they are garbage- is flushed). Channels are automatically closed when their L{Transport}
collected, or when their L{Transport} is closed. is closed.
Note that because of peculiarities with the way python's garbage
collection works on cycles, channels will B{not} be automatically
closed by the garbage collector.
""" """
self.lock.acquire() self.lock.acquire()
try: try:
if not self.active or self.closed: if not self.active or self.closed:
return return
try: self._close_internal()
self._send_eof()
m = Message() # only close the pipe when the user explicitly closes the channel.
m.add_byte(chr(MSG_CHANNEL_CLOSE)) # otherwise they will get unpleasant surprises.
m.add_int(self.remote_chanid) if self.pipe is not None:
self.transport._send_user_message(m) print 'closing pipe!'
except EOFError: self.pipe.close()
pass self.pipe = None
self._set_closed()
# can't unlink from the Transport yet -- the remote side may still
# try to send meta-data (exit-status, etc)
finally: finally:
self.lock.release() self.lock.release()
@ -862,7 +863,11 @@ class Channel (object):
return return
def _request_failed(self, m): def _request_failed(self, m):
self.close() self.lock.acquire()
try:
self._close_internal()
finally:
self.lock.release()
def _feed(self, m): def _feed(self, m):
if type(m) is str: if type(m) is str:
@ -980,20 +985,16 @@ class Channel (object):
self.in_buffer_cv.notifyAll() self.in_buffer_cv.notifyAll()
self.in_stderr_buffer_cv.notifyAll() self.in_stderr_buffer_cv.notifyAll()
if self.pipe is not None: if self.pipe is not None:
self.pipe.close() self.pipe.set()
self.pipe = None
finally: finally:
self.lock.release() self.lock.release()
self._log(DEBUG, 'EOF received') self._log(DEBUG, 'EOF received')
def _handle_close(self, m): def _handle_close(self, m):
self.close()
self.lock.acquire() self.lock.acquire()
try: try:
self._close_internal()
self.transport._unlink_channel(self.chanid) self.transport._unlink_channel(self.chanid)
if self.pipe is not None:
self.pipe.close()
self.pipe = None
finally: finally:
self.lock.release() self.lock.release()
@ -1023,6 +1024,22 @@ class Channel (object):
self._log(DEBUG, 'EOF sent') self._log(DEBUG, 'EOF sent')
return return
def _close_internal(self):
# you are holding the lock.
if not self.active or self.closed:
return
try:
self._send_eof()
m = Message()
m.add_byte(chr(MSG_CHANNEL_CLOSE))
m.add_int(self.remote_chanid)
self.transport._send_user_message(m)
except EOFError:
pass
self._set_closed()
# can't unlink from the Transport yet -- the remote side may still
# try to send meta-data (exit-status, etc)
def _unlink(self): def _unlink(self):
# server connection could die before we become active: still signal the close! # server connection could die before we become active: still signal the close!
if self.closed: if self.closed: