New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: handle timeout error in client #2067
base: main
Are you sure you want to change the base?
Fix: handle timeout error in client #2067
Conversation
Hello @bitprophet 👋 Can you check this PR? Thanks a lot ❤ |
Hi, @gquittet -- thanks for putting this together! A couple of questions:
|
@jun66j5 If I read #279 (comment) correctly, |
Hello @bskinn 👋
Have a nice day/night 😉 |
I don't consider that it is needed to add/change from Actually, $ python3.6
Python 3.6.15 (default, Apr 25 2022, 01:55:53)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.setsockopt(socket.IPPROTO_TCP, socket.TCP_USER_TIMEOUT, 1000) # 1,000 ms
>>> try:
... s.connect(('192.0.2.1', 22))
... except socket.error as e:
... print('socket.error: %s %s' % (type(e), e))
...
socket.error: <class 'TimeoutError'> [Errno 110] Connection timed out $ python2.7
Python 2.7.18 (default, Mar 8 2021, 13:02:45)
[GCC 9.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> TCP_USER_TIMEOUT = 18
>>> s.setsockopt(socket.IPPROTO_TCP, TCP_USER_TIMEOUT, 1000) # 1,000 ms
>>> try:
... s.connect(('192.0.2.1', 22))
... except socket.error as e:
... print('socket.error: %s %s' % (type(e), e))
...
socket.error: <class 'socket.error'> [Errno 110] Connection timed out
>>> import errno
>>> errno.ETIMEDOUT
110 |
After the changes: >>> import paramiko
>>> client = paramiko.SSHClient()
>>> client.connect('192.0.2.1', timeout=3600)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jun66j5/src/paramiko/paramiko/client.py", line 372, in connect
raise NoValidConnectionsError(errors)
paramiko.ssh_exception.NoValidConnectionsError: [Errno None] Unable to connect to port 22 on 192.0.2.1 |
45c801f
to
77b65b4
Compare
77b65b4
to
79a5b81
Compare
79a5b81
to
3af117a
Compare
I also sort the import but I can drop the commit if you don't like |
I noticed >>> client.connect('192.0.2.1', timeout=1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/jun66j5/src/paramiko/paramiko/client.py", line 349, in connect
retry_on_signal(lambda: sock.connect(addr))
File "/home/jun66j5/src/paramiko/paramiko/util.py", line 279, in retry_on_signal
return function()
File "/home/jun66j5/src/paramiko/paramiko/client.py", line 349, in <lambda>
retry_on_signal(lambda: sock.connect(addr))
socket.timeout: timed out We should check whether the exception is a @@ -356,7 +356,11 @@ class SSHClient(ClosingContextManager):
sock.close()
# Raise anything that isn't a straight up connection error
# (such as a resolution error)
- if e.errno not in (ECONNREFUSED, EHOSTUNREACH):
+ if not isinstance(e, socket.timeout) and e.errno not in (
+ ECONNREFUSED,
+ EHOSTUNREACH,
+ ETIMEDOUT,
+ ):
raise
# Capture anything else so we know how the run looks once
# iteration is complete. Retain info about which attempt |
Sometimes, we can't connect to a specific device because of a timeout error.
You can see the stacktrace below:
Simple code to reproduce the issue:
Related to: #279