diff --git a/paramiko/packet.py b/paramiko/packet.py index 00cf56578..c943fe3c3 100644 --- a/paramiko/packet.py +++ b/paramiko/packet.py @@ -103,6 +103,10 @@ def __init__(self, socket): 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 d362ea64c..000a98f30 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -1533,8 +1533,17 @@ def getpeername(self): 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...