summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2022-06-03 19:55:51 -0400
committerJeff Forcier <jeff@bitprophet.org>2022-06-03 19:55:51 -0400
commit0f3beefa5618ca46ea880eca696dca488fcc2bb6 (patch)
treeaae2a285cc2821c7e2b042bf28e2d2a08f0b74d5
parent00fce050cb33fb5ec1f13811c1ad8188cf11645d (diff)
parent92920c113740d768ccb311b103fdd744389304b1 (diff)
downloadparamiko-0f3beefa5618ca46ea880eca696dca488fcc2bb6.tar.gz
Merge branch '2.10' into 2.11
-rw-r--r--paramiko/client.py4
-rw-r--r--sites/www/changelog.rst7
-rw-r--r--tests/test_client.py18
3 files changed, 29 insertions, 0 deletions
diff --git a/paramiko/client.py b/paramiko/client.py
index 581f9b6f..92feaa1f 100644
--- a/paramiko/client.py
+++ b/paramiko/client.py
@@ -350,6 +350,10 @@ class SSHClient(ClosingContextManager):
# Break out of the loop on success
break
except socket.error as e:
+ # As mentioned in socket docs it is better
+ # to close sockets explicitly
+ if sock:
+ sock.close()
# Raise anything that isn't a straight up connection error
# (such as a resolution error)
if e.errno not in (ECONNREFUSED, EHOSTUNREACH):
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index 920bca10..87c5faf2 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,13 @@
Changelog
=========
+- :bug:`1822` (via, and relating to, far too many other issues to mention here)
+ Update `~paramiko.client.SSHClient` so it explicitly closes its wrapped
+ socket object upon encountering socket errors at connection time. This should
+ help somewhat with certain classes of memory leaks, resource warnings, and/or
+ errors (though we hasten to remind everyone that Client and Transport have
+ their own ``.close()`` methods for use in non-error situations!). Patch
+ courtesy of ``@YoavCohen``.
- bug:`1637` (via :issue:`1599`) Raise `SSHException` explicitly when blank
private key data is loaded, instead of the natural result of ``IndexError``.
This should help more bits of Paramiko or Paramiko-adjacent codebases to
diff --git a/tests/test_client.py b/tests/test_client.py
index 3db4cd22..fd54140b 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -33,6 +33,7 @@ import warnings
import weakref
from tempfile import mkstemp
+import pytest
from pytest_relaxed import raises
from mock import patch, Mock
@@ -473,6 +474,23 @@ class SSHClientTest(ClientTest):
assert p() is None
+ @patch("paramiko.client.socket.socket")
+ @patch("paramiko.client.socket.getaddrinfo")
+ def test_closes_socket_on_socket_errors(self, getaddrinfo, mocket):
+ getaddrinfo.return_value = (
+ ("irrelevant", None, None, None, "whatever"),
+ )
+
+ class SocksToBeYou(socket.error):
+ pass
+
+ my_socket = mocket.return_value
+ my_socket.connect.side_effect = SocksToBeYou
+ client = SSHClient()
+ with pytest.raises(SocksToBeYou):
+ client.connect(hostname="nope")
+ my_socket.close.assert_called_once_with()
+
def test_client_can_be_used_as_context_manager(self):
"""
verify that an SSHClient can be used a context manager