From 2f13f99e69c5f985bd255912f115a2afea573d4f Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 20 May 2024 15:10:36 -0400 Subject: [PATCH 1/3] Handle dlopen(NULL) failure in glibc fallback --- src/pip/_internal/utils/glibc.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/utils/glibc.py b/src/pip/_internal/utils/glibc.py index 81342afa447..e89dda7ebf4 100644 --- a/src/pip/_internal/utils/glibc.py +++ b/src/pip/_internal/utils/glibc.py @@ -40,7 +40,20 @@ def glibc_version_string_ctypes() -> Optional[str]: # manpage says, "If filename is NULL, then the returned handle is for the # main program". This way we can let the linker do the work to figure out # which libc our process is actually using. - process_namespace = ctypes.CDLL(None) + # + # We must also handle the special case where the executable is not a + # dynamically linked executable. This can occur when using musl libc, + # for example. In this situation, dlopen() will error, leading to an + # OSError. Interestingly, at least in the case of musl, there is no + # errno set on the OSError. The single string argument used to construct + # OSError comes from libc itself and is therefore not portable to + # hard code here. In any case, failure to call dlopen() means we + # can proceed, so we bail on our attempt. + try: + process_namespace = ctypes.CDLL(None) + except OSError: + return None + try: gnu_get_libc_version = process_namespace.gnu_get_libc_version except AttributeError: @@ -50,7 +63,7 @@ def glibc_version_string_ctypes() -> Optional[str]: # Call gnu_get_libc_version, which returns a string like "2.5" gnu_get_libc_version.restype = ctypes.c_char_p - version_str = gnu_get_libc_version() + version_str: str = gnu_get_libc_version() # py2 / py3 compatibility: if not isinstance(version_str, str): version_str = version_str.decode("ascii") From 897d9d440451c3947bda0ffbc22b47d93fc805e1 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 20 May 2024 15:18:00 -0400 Subject: [PATCH 2/3] Add news --- news/12716.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/12716.bugfix.rst diff --git a/news/12716.bugfix.rst b/news/12716.bugfix.rst new file mode 100644 index 00000000000..7af794f7bb3 --- /dev/null +++ b/news/12716.bugfix.rst @@ -0,0 +1 @@ +Avoid dlopen failure for glibc detection in musl builds From 6009e3d04e00adf9e11f512cc10226a58239792e Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Wed, 10 Jul 2024 00:50:22 +0100 Subject: [PATCH 3/3] Apply suggestions from code review Co-authored-by: Richard Si --- src/pip/_internal/utils/glibc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/utils/glibc.py b/src/pip/_internal/utils/glibc.py index e89dda7ebf4..998868ff2a4 100644 --- a/src/pip/_internal/utils/glibc.py +++ b/src/pip/_internal/utils/glibc.py @@ -48,7 +48,7 @@ def glibc_version_string_ctypes() -> Optional[str]: # errno set on the OSError. The single string argument used to construct # OSError comes from libc itself and is therefore not portable to # hard code here. In any case, failure to call dlopen() means we - # can proceed, so we bail on our attempt. + # can't proceed, so we bail on our attempt. try: process_namespace = ctypes.CDLL(None) except OSError: