-
-
Notifications
You must be signed in to change notification settings - Fork 31k
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
The loop in utility socket.create_connection()
swallows previous errors
#73943
Comments
ContextThe utility method
The problemSo currently the loop in ## Possible solutions & open questions A question for cases (a) & (b) is what logging "means" to use: the Case (c) sidesteps the above questions. |
I like the (c) option. I don't think we should use logging/warnings here, as they can produce unwanted noise that few know how to silence. When the list of errors is passed as a second argument to the exception, how is it rendered? Would it make sense to concatenate all error messages: if errs:
errors_msg = ' \n'.join(str(e) for e in errs)
raise error(f"connection failed:\n{errors_msg}", errs) Or maybe we should track which addr caused which exception? for res in getaddrinfo(host, port, 0, SOCK_STREAM):
af, socktype, proto, canonname, sa = res
try:
...
except error as e:
errs.append((canonname, e))
...
if errs:
error_msg = ' \n'.join(f'{addr}: {e}' for addr, e in errs)
raise error('connection failed:\n{error_msg}', errs) |
This is a new feature, so we can only push it to 3.7. |
This is how my latest ec887c0c3 looks on Linux: >>> import socket
>>> socket.create_connection(('localhost', 12345))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.5/socket.py", line 714, in create_connection
raise error("no connection possible due to %d errors" % nerr, errors)
OSError: [Errno no connection possible due to 2 errors] [ConnectionRefusedError(111, 'Connection refused'), ConnectionRefusedError(111, 'Connection refused')] And this is on Windows: >>> socket.create_connection(('localhost', 12345), 1)
Traceback (most recent call last):
File "D:\Apps\WinPython-64bit-3.5.3.0Qt5\python-3.5.3.amd64\lib\site-packages\IPython\core\interactiveshell.py", line 2881, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-13-758ac642f3d5>", line 1, in <module>
socket.create_connection(('localhost', 12345), 1)
File "D:\Apps\WinPython-64bit-3.5.3.0Qt5\python-3.5.3.amd64\lib\socket.py", line 714, in create_connection
raise error("no connection possible due to %d errors" % nerr, errors)
OSError: [Errno no connection possible due to 2 errors] [timeout('timed out',), timeout('timed out',)]
But then the user will not receive a list of errors to inspect, but just a big string. And still, this PR is not yer finished because there is no feedback on any intermediate errors in the case of success.
I prefer logging over warnings because they are more configurable. [1] https://github.com/python/cpython/blob/master/Lib/socket.py#L724 |
As it stands now(b39d4b1) it hardly contains any change - just in the case of multiple intermediate errors AND final failure, the exception raised is a bit different. AFAICS it would be a "change" for 3.7 if my one of the 3 options of my last comment gets implemented. Any ideas which one to implement? |
Just to remind that as it stands now(b39d4b1) it contains no API changes at all, so it should be considered for merge into 3.6.x line. |
I'm not excited to keep multiple exception objects alive because the Exception.__traceback__ causes many hairy reference cycle issues. I just found an old bug in socket.create_connection(): See https://bugs.python.org/issue29639#msg302087 for my story of the bug. |
I propose the close the issue as WONTFIX. I don't see how the current behavior is an issue. I expect a very large traceback just because a server is down/reject connections. I'm not sure that I want that by default.
It's not so hard to reimplement create_connection(): it's a loop on getaddrinfo(). So you can decide how to deal with errors. -- I recall that Yury Selivanov, Nathnaniel Smith and Guido van Rossum discussed the idea of "MultiError": an object which contains multiple exceptions, object which would render properly all exceptions when a traceback is displayed. |
The problem of not fixing this (and just add a suggestion in the docs saying that the user may re-implement this method) is that frequently this call is hidden at the core of many networking libraries. So monkey-patching is needed instead, which is not always nice or easy.
Regarding bpo-3546, i'm surprised that a function-local variable keeps its contents alive, long after the frame of that function has gone. I thought that local-variables were deterministically (ref-countering) destructed. |
IT's a reference cycle. Exception => traceback => frame => exception. The 'err' variable kept the frame alive which kept the exception alive which kept everything alive. The GC is supposed to be able to break ref cycles, but GC collections are irregular and sometimes the GC fails to break complex cycles. |
This is a duplicate of #74166. |
socket.create_connection()
utility loop #562Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: