diff options
author | Omer Anson <omer.anson@toganetworks.com> | 2017-02-09 18:59:03 +0200 |
---|---|---|
committer | Jeff Forcier <jeff@bitprophet.org> | 2017-02-20 14:40:14 -0800 |
commit | 718e821b4a6d68b0daf3e7061a1cc78ee8389896 (patch) | |
tree | bcdd539f961419b4a2bd90bc113c544fba4b4e00 | |
parent | 11f4c2fa13aadd000a22f33edb9ef4d70cf03236 (diff) |
Add back-reference from Transport to the SSHClient that created it
In some cases, the SSH client is created, the command is executed, the
streams are extracted, and the explicit reference to SSHClient is then
discarded (since it was e.g. created in a function that only returns the
streams). In this case, the SHSClient may be garbage collected, and the
connection's state is undefined.
This fix adds a reference from Transport to the SSHClient that created
it. The streams have a reference to the Channel, which references the
Transport. Now that the Transport references the SSHClient, it won't be
garbage collected until it is closed.
Closes-Bug: #44
Related-Bug: #344
-rw-r--r-- | paramiko/client.py | 1 | ||||
-rw-r--r-- | paramiko/transport.py | 5 |
2 files changed, 6 insertions, 0 deletions
diff --git a/paramiko/client.py b/paramiko/client.py index ebf21b08..18139416 100644 --- a/paramiko/client.py +++ b/paramiko/client.py @@ -336,6 +336,7 @@ class SSHClient (ClosingContextManager): if banner_timeout is not None: t.banner_timeout = banner_timeout t.start_client() + t.set_sshclient(self) ResourceManager.register(self, t) server_key = t.get_remote_server_key() diff --git a/paramiko/transport.py b/paramiko/transport.py index f1d590ec..6d7dd0e8 100644 --- a/paramiko/transport.py +++ b/paramiko/transport.py @@ -282,6 +282,7 @@ class Transport (threading.Thread, ClosingContextManager): arguments. """ self.active = False + self._sshclient = None if isinstance(sock, string_types): # convert "host:port" into (host, port) @@ -637,6 +638,9 @@ class Transport (threading.Thread, ClosingContextManager): Transport._modulus_pack = None return False + def set_sshclient(self, sshclient): + self._sshclient = sshclient + def close(self): """ Close this session, and any open channels that are tied to it. @@ -647,6 +651,7 @@ class Transport (threading.Thread, ClosingContextManager): for chan in list(self._channels.values()): chan._unlink() self.sock.close() + self._sshclient = None def get_remote_server_key(self): """ |