Only query host address families over DNS that the local network stack supports#5176
Only query host address families over DNS that the local network stack supports#5176webknjaz merged 9 commits intoaio-libs:masterfrom
Conversation
asvetlov
left a comment
There was a problem hiding this comment.
I like this PR
@danielnelson could you please check the pull request and make sure that the problem disappeared?
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #5176 +/- ##
=======================================
Coverage 97.45% 97.45%
=======================================
Files 43 43
Lines 8779 8779
Branches 1412 1412
=======================================
Hits 8556 8556
Misses 112 112
Partials 111 111
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
|
@asvetlov the code cov check failed because #4556 was merged without coverage of the line if family == socket.AF_INET6 and address[3]: # type: ignoreI can add a unit test for this branch as well to bypass the coverage check, but I don't understand how the mock data should look like. Also in https://docs.aiohttp.org/en/latest/contributing.html is mentioned about $ make cov
make: *** No rule to make target 'cov'. Stop. |
$ cat bug.py
import asyncio
import aiohttp
async def main():
async with aiohttp.ClientSession() as session:
async with session.get('http://python.org') as response:
print(response.status)
asyncio.run(main())$ python bug.py
Bad address format in (<AddressFamily.AF_INET6: 10>, <SocketKind.SOCK_STREAM: 1>, 6, '', (10, b'\x01\xbb\x00\x00\x00\x00*\x04NB\x00-\x00\x00'))
200
Future exception was never retrieved
future: <Future finished exception=SSLError(1, '[SSL: KRB5_S_INIT] application data after close notify (_ssl.c:2691)')>
Traceback (most recent call last):
File "/usr/lib/python3.7/asyncio/sslproto.py", line 530, in data_received
ssldata, appdata = self._sslpipe.feed_ssldata(data)
File "/usr/lib/python3.7/asyncio/sslproto.py", line 207, in feed_ssldata
self._sslobj.unwrap()
File "/usr/lib/python3.7/ssl.py", line 778, in unwrap
return self._sslobj.shutdown()
ssl.SSLError: [SSL: KRB5_S_INIT] application data after close notify (_ssl.c:2691)Not sure what that SSLError is about, possibly I did something incorrect when compiling? I suspect that this patch would be very noisy to run, as every remote with an IPv6 address would log. |
|
If I enable the AsyncResolver it also raises: Traceback (most recent call last):
File "/home/dbn/src/aiohttp/aiohttp/connector.py", line 940, in _wrap_create_connection
return await self._loop.create_connection(*args, **kwargs) # type: ignore # noqa
File "/usr/lib/python3.7/asyncio/base_events.py", line 962, in create_connection
raise exceptions[0]
File "/usr/lib/python3.7/asyncio/base_events.py", line 928, in create_connection
sock = socket.socket(family=family, type=type, proto=proto)
File "/usr/lib/python3.7/socket.py", line 151, in __init__
_socket.socket.__init__(self, family, type, proto, fileno)
OSError: [Errno 97] Address family not supported by protocol
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "bug.py", line 13, in <module>
asyncio.run(main())
File "/usr/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
return future.result()
File "bug.py", line 9, in main
async with session.get(sys.argv[1]) as response:
File "/home/dbn/src/aiohttp/aiohttp/client.py", line 1070, in __aenter__
self._resp = await self._coro
File "/home/dbn/src/aiohttp/aiohttp/client.py", line 482, in _request
req, traces=traces, timeout=real_timeout
File "/home/dbn/src/aiohttp/aiohttp/connector.py", line 508, in connect
proto = await self._create_connection(req, traces, timeout)
File "/home/dbn/src/aiohttp/aiohttp/connector.py", line 863, in _create_connection
_, proto = await self._create_direct_connection(req, traces, timeout)
File "/home/dbn/src/aiohttp/aiohttp/connector.py", line 1021, in _create_direct_connection
raise last_exc
File "/home/dbn/src/aiohttp/aiohttp/connector.py", line 1003, in _create_direct_connection
client_error=client_error,
File "/home/dbn/src/aiohttp/aiohttp/connector.py", line 946, in _wrap_create_connection
raise client_error(req.connection_key, exc) from exc
aiohttp.client_exceptions.ClientConnectorError: Cannot connect to host www.python.org:80 ssl:default [Address family not supported by protocol] |
|
@danielnelson looks like the code passed the resolver and tries to use secured connection for http. |
webknjaz
left a comment
There was a problem hiding this comment.
I'm pretty sure that the correct solution should be setting the AI_ADDRCONFIG flag: #5156 (comment).
|
@webknjaz hosts.append(
{
"hostname": hostname,
"host": host,
"port": port,
"family": family,
"proto": proto,
"flags": socket.AI_NUMERICHOST | socket.AI_NUMERICSERV,
}
)? |
|
@derlih no, that thing is copied from |
|
@danielnelson please verify that this fix works for you. |
|
Yes, this patch is working great! If anyone needs to reproduce, I needed to update my test script to read the response in order to avoid the import asyncio
import aiohttp
import sys
async def main():
async with aiohttp.ClientSession() as session:
async with session.get(sys.argv[1]) as response:
print(response.status)
await response.read()
asyncio.run(main())Of course, this change does not resolve the issue if using the AsyncResolver. Would it make sense for me to open a new issue for this? |
|
Ok, let's apply the patch. Thank you all, and especially @derlih for the patch (and patience in the patch implementation changing). @webknjaz do you want to approve it? |
…k supports (#5176) * Fix for #5156 * test for #5156 * add changes file * rearrange if/else * Revert "rearrange if/else" This reverts commit a557e4c. * Revert "test for #5156" This reverts commit 9d81913. * Revert "Fix for #5156" This reverts commit 48de143. * Add AI_ADDRCONFIG flag to loop.getaddrinfo * update changes file
…k supports (#5176) * Fix for #5156 * test for #5156 * add changes file * rearrange if/else * Revert "rearrange if/else" This reverts commit a557e4c. * Revert "test for #5156" This reverts commit 9d81913. * Revert "Fix for #5156" This reverts commit 48de143. * Add AI_ADDRCONFIG flag to loop.getaddrinfo * update changes file
…k supports (#5176) (#5190) * Fix for #5156 * test for #5156 * add changes file * rearrange if/else * Revert "rearrange if/else" This reverts commit a557e4c. * Revert "test for #5156" This reverts commit 9d81913. * Revert "Fix for #5156" This reverts commit 48de143. * Add AI_ADDRCONFIG flag to loop.getaddrinfo * update changes file Co-authored-by: Dmitry Erlikh <[email protected]>
…k supports (#5176) (#5189) * Fix for #5156 * test for #5156 * add changes file * rearrange if/else * Revert "rearrange if/else" This reverts commit a557e4c. * Revert "test for #5156" This reverts commit 9d81913. * Revert "Fix for #5156" This reverts commit 48de143. * Add AI_ADDRCONFIG flag to loop.getaddrinfo * update changes file Co-authored-by: Dmitry Erlikh <[email protected]>
…k supports (aio-libs#5176) * Fix for aio-libs#5156 * test for aio-libs#5156 * add changes file * rearrange if/else * Revert "rearrange if/else" This reverts commit a557e4c. * Revert "test for aio-libs#5156" This reverts commit 9d81913. * Revert "Fix for aio-libs#5156" This reverts commit 48de143. * Add AI_ADDRCONFIG flag to loop.getaddrinfo * update changes file
…k supports (aio-libs#5176) * Fix for aio-libs#5156 * test for aio-libs#5156 * add changes file * rearrange if/else * Revert "rearrange if/else" This reverts commit a557e4c. * Revert "test for aio-libs#5156" This reverts commit 9d81913. * Revert "Fix for aio-libs#5156" This reverts commit 48de143. * Add AI_ADDRCONFIG flag to loop.getaddrinfo * update changes file
What do these changes do?
Workaround for incorrect socket.getaddrinfo return value in rare case
Are there changes in behavior for the user?
No
Related issue number
Fixes #5156
Checklist
CONTRIBUTORS.txtCHANGESfolder<issue_id>.<type>for example (588.bugfix)issue_idchange it to the pr id after creating the pr.feature: Signifying a new feature..bugfix: Signifying a bug fix..doc: Signifying a documentation improvement..removal: Signifying a deprecation or removal of public API..misc: A ticket has been closed, but it is not of interest to users.