From ed77581d7a8a36af5a141d8bac41213aa9ef750a Mon Sep 17 00:00:00 2001 From: Robey Pointer Date: Mon, 17 May 2004 07:41:50 +0000 Subject: [PATCH] [project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-52] fix deadlock in closing a channel closing a channel would enter an odd codepath where the lock was grabbed, some stuff was done, then another function was called where the lock was grabbed again. unfortunately python locks aren't monitors so this would deadlock. instead, make the smaller function lock-free with an explicit notice that you must be holding the lock before calling. --- paramiko/channel.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/paramiko/channel.py b/paramiko/channel.py index b339f31..2f5968d 100644 --- a/paramiko/channel.py +++ b/paramiko/channel.py @@ -724,13 +724,10 @@ class Channel (object): self.logger.log(level, msg) def _set_closed(self): + # you are holding the lock. self.closed = True - try: - self.lock.acquire() - self.in_buffer_cv.notifyAll() - self.out_buffer_cv.notifyAll() - finally: - self.lock.release() + self.in_buffer_cv.notifyAll() + self.out_buffer_cv.notifyAll() def _send_eof(self): if self.eof_sent: @@ -824,8 +821,12 @@ class Channel (object): def _unlink(self): if self.closed or not self.active: return - self._set_closed() - self.transport._unlink_channel(self.chanid) + try: + self.lock.acquire() + self._set_closed() + self.transport._unlink_channel(self.chanid) + finally: + self.lock.release() def _check_add_window(self, n): # already holding the lock!