From 3f92d92a3f7d44a46d69dd10a1fe4bbeca11836e Mon Sep 17 00:00:00 2001 From: Douglas Raillard Date: Fri, 15 Oct 2021 15:24:53 +0100 Subject: [PATCH] ssh: Reduce number of opened channels SSH servers seem to have a maximum number of opened channels, after which paramiko will raise an exception: Could not open an SSH channel: ChannelException(2, 'Connect failed') Memoizing the SFTPClient object based on the timeout setting leads to many opened sessions, since the timeout is typically adjusted, e.g. to match the size of the file when pulling an ftrace trace.dat file. Solve that by memoizing the SFTPClient based only on the connection object, with a maximum number of 1 cached object, and update its timeout setting inplace. --- devlib/utils/ssh.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/devlib/utils/ssh.py b/devlib/utils/ssh.py index 2586d62..3a92fb5 100644 --- a/devlib/utils/ssh.py +++ b/devlib/utils/ssh.py @@ -410,8 +410,11 @@ class SshConnection(SshConnectionBase): def _get_progress_cb(self): return self.transfer_mgr.progress_cb if self.transfer_mgr is not None else None - @functools.lru_cache() - def _get_sftp(self, timeout): + # Limit the number of opened channels to a low number, since some servers + # will reject more connections request. For OpenSSH, this is controlled by + # the MaxSessions config. + @functools.lru_cache(maxsize=1) + def _cached_get_sftp(self): try: sftp = self.client.open_sftp() except paramiko.ssh_exception.SSHException as e: @@ -419,6 +422,10 @@ class SshConnection(SshConnectionBase): raise TargetStableError('The SSH server does not support SFTP. Please install and enable appropriate module.') from e else: raise + return sftp + + def _get_sftp(self, timeout): + sftp = self._cached_get_sftp() sftp.get_channel().settimeout(timeout) return sftp