diff options
-rw-r--r-- | paramiko/packet.py | 4 | ||||
-rw-r--r-- | paramiko/transport.py | 13 |
2 files changed, 15 insertions, 2 deletions
diff --git a/paramiko/packet.py b/paramiko/packet.py index 89a514d1..5dd4c49f 100644 --- a/paramiko/packet.py +++ b/paramiko/packet.py @@ -103,6 +103,10 @@ class Packetizer (object): self.__handshake_complete = False self.__timer_expired = False + @property + def closed(self): + return self.__closed + def set_log(self, log): """ Set the Python log object to use for logging. diff --git a/paramiko/transport.py b/paramiko/transport.py index 5e175230..64b96d4f 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -1532,8 +1532,17 @@ class Transport (threading.Thread, ClosingContextManager): def stop_thread(self): self.active = False self.packetizer.close() - while self.is_alive() and (self is not threading.current_thread()): - self.join(10) + # Keep trying to join() our main thread, quickly, until: + # * We join()ed successfully (self.is_alive() == False) + # * Or it looks like we've hit issue #520 (socket.recv hitting some + # race condition preventing it from timing out correctly), wherein our + # socket and packetizer are both closed (but where we'd otherwise be + # sitting forever on that recv()). + while ( + self.is_alive() and self is not threading.current_thread() + and not self.sock._closed and not self.packetizer.closed + ): + self.join(0.1) ### internals... |