-
Notifications
You must be signed in to change notification settings - Fork 1.1k
PYTHON-5021 - Fix usages of getaddrinfo to be non-blocking #2059
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
Changes from 1 commit
f7bb39e
882c0db
f6c0136
076a014
2821566
26fe6e1
297bf9c
39ade36
5e3bc65
85e59fd
abe6b24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
"""Authentication helpers.""" | ||
from __future__ import annotations | ||
|
||
import asyncio | ||
import functools | ||
import hashlib | ||
import hmac | ||
|
@@ -177,15 +178,28 @@ def _auth_key(nonce: str, username: str, password: str) -> str: | |
return md5hash.hexdigest() | ||
|
||
|
||
def _canonicalize_hostname(hostname: str, option: str | bool) -> str: | ||
async def _canonicalize_hostname(hostname: str, option: str | bool) -> str: | ||
"""Canonicalize hostname following MIT-krb5 behavior.""" | ||
# https://github.com/krb5/krb5/blob/d406afa363554097ac48646a29249c04f498c88e/src/util/k5test.py#L505-L520 | ||
if option in [False, "none"]: | ||
return hostname | ||
|
||
af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( | ||
hostname, None, 0, 0, socket.IPPROTO_TCP, socket.AI_CANONNAME | ||
)[0] | ||
if not _IS_SYNC: | ||
loop = asyncio.get_event_loop() | ||
af, socktype, proto, canonname, sockaddr = ( | ||
await loop.getaddrinfo( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI:
https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.getaddrinfo Which means our users will eventually run into this issue: python/cpython#112169 This is still better than blocking the loop of course but I wonder if we need to warn of this potential problem or if we should test it explicitly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would explicitly testing it provide an actionable solution? We could increase the default number of workers to help mitigate this, but warning users might only confuse them since this is an internal API. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we instead use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our current uses of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My point is that user's code will default to the default executor, so we'd be contending with its resources. We'd be essentially taking Guido's advice and applying it to a library so it doesn't interfere with a default user. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, you're saying we use our own There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does if the OS thread limit is much higher than the default thread executor's thread limit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, I like that idea then. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would also suggest making a utility function for |
||
hostname, | ||
None, | ||
family=0, | ||
type=0, | ||
proto=socket.IPPROTO_TCP, | ||
flags=socket.AI_CANONNAME, | ||
) | ||
)[0] # type: ignore[index] | ||
else: | ||
af, socktype, proto, canonname, sockaddr = socket.getaddrinfo( | ||
hostname, None, 0, 0, socket.IPPROTO_TCP, socket.AI_CANONNAME | ||
)[0] | ||
|
||
# For forward just to resolve the cname as dns.lookup() will not return it. | ||
if option == "forward": | ||
|
@@ -213,7 +227,7 @@ async def _authenticate_gssapi(credentials: MongoCredential, conn: AsyncConnecti | |
# Starting here and continuing through the while loop below - establish | ||
# the security context. See RFC 4752, Section 3.1, first paragraph. | ||
host = props.service_host or conn.address[0] | ||
host = _canonicalize_hostname(host, props.canonicalize_host_name) | ||
host = await _canonicalize_hostname(host, props.canonicalize_host_name) | ||
service = props.service_name + "@" + host | ||
if props.service_realm is not None: | ||
service = service + "@" + props.service_realm | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be get_running_loop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, "Because this function has rather complex behavior (especially when custom event loop policies are in use), using the get_running_loop() function is preferred to get_event_loop() in coroutines and callbacks.".
https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.get_event_loop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good find--we use
asyncio.get_event_loop()
elsewhere in the code, I'll open a separate ticket to change those uses as well.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed for the rest of the codebase in #2063.