From f6e1e84d60ae75cd28030b4c41856ec768566a46 Mon Sep 17 00:00:00 2001 From: Robey Pointer Date: Wed, 24 Dec 2003 22:09:43 +0000 Subject: [PATCH] [project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-13] fix a deadlock/race in handle_eof & close (patch from fred gansevles) add locking around the eof handler and the close() call, so we can't be in both simultaneously. --- channel.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/channel.py b/channel.py index de1e31e..fa0ff7c 100644 --- a/channel.py +++ b/channel.py @@ -158,13 +158,14 @@ class Channel(object): self.transport.send_message(m) def handle_eof(self, m): - self.eof_received = 1 try: self.lock.acquire() - self.in_buffer_cv.notifyAll() - if self.pipe_wfd != None: - os.close(self.pipe_wfd) - self.pipe_wfd = None + if not self.eof_received: + self.eof_received = 1 + self.in_buffer_cv.notifyAll() + if self.pipe_wfd != None: + os.close(self.pipe_wfd) + self.pipe_wfd = None finally: self.lock.release() self.log(DEBUG, 'EOF received') @@ -282,15 +283,18 @@ class Channel(object): self.settimeout(0.0) def close(self): - if self.closed or not self.active: - return - self.send_eof() - m = Message() - m.add_byte(chr(MSG_CHANNEL_CLOSE)) - m.add_int(self.remote_chanid) - self.transport.send_message(m) - self.closed = 1 - self.transport.unlink_channel(self.chanid) + try: + self.lock.acquire() + if self.active and not self.closed: + self.send_eof() + m = Message() + m.add_byte(chr(MSG_CHANNEL_CLOSE)) + m.add_int(self.remote_chanid) + self.transport.send_message(m) + self.closed = 1 + self.transport.unlink_channel(self.chanid) + finally: + self.lock.release() def recv_ready(self): "doesn't work if you've called fileno()"