Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cpython-unix/build-cpython.sh
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,11 @@ if [ -n "${CROSS_COMPILING}" ]; then
# TODO: There are probably more of these, see #599.
fi

# TODO description
if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
patch -p1 -i "${ROOT}/patch-python-getpath-3.14.patch"
fi

# We patched configure.ac above. Reflect those changes.
autoconf

Expand Down
105 changes: 105 additions & 0 deletions cpython-unix/patch-python-getpath-3.14.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
From 4c69b0e246bd1057f640f87dfa5937a032f32f83 Mon Sep 17 00:00:00 2001
From: Geoffrey Thomas <[email protected]>
Date: Mon, 1 Dec 2025 14:11:43 -0500
Subject: [PATCH 1/1] getpath: Fix library detection and canonicalize paths

TODO description
---
Modules/getpath.c | 43 +++++++++++++++++++++++++++++++++++++------
Modules/getpath.py | 4 ++--
2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/Modules/getpath.c b/Modules/getpath.c
index 1e75993480a..f8fc1608de4 100644
--- a/Modules/getpath.c
+++ b/Modules/getpath.c
@@ -802,14 +802,16 @@ progname_to_dict(PyObject *dict, const char *key)
}


+static void
+fclose_cleanup(FILE **pf) {
+ fclose(*pf);
+}
+
+
/* Add the runtime library's path to the dict */
static int
library_to_dict(PyObject *dict, const char *key)
{
-/* macOS framework builds do not link against a libpython dynamic library, but
- instead link against a macOS Framework. */
-#if defined(Py_ENABLE_SHARED) || defined(WITH_NEXT_FRAMEWORK)
-
#ifdef MS_WINDOWS
extern HMODULE PyWin_DLLhModule;
if (PyWin_DLLhModule) {
@@ -817,12 +819,41 @@ library_to_dict(PyObject *dict, const char *key)
}
#endif

+ const void *target = (void *)Py_Initialize;
+
+#ifdef __linux__
+ /* Linux libcs do not reliably report the canonical path in dli_fname, but
+ * we have /proc/self/maps. (dyld seems to reliably report the canonical
+ * path, so this matches the behavior on macOS.) */
+
+ FILE *maps __attribute__((cleanup(fclose_cleanup))) = fopen("/proc/self/maps", "r");
+ if (maps != NULL) {
+ /* Format is documented in proc_pid_maps(5), but you want to look at
+ * the implementation in fs/proc/task_mmu.c for spacing. The pathname
+ * is the last field and has any \n characters escaped, so we can read
+ * until \n. Note that the filename may have " (deleted)" appended;
+ * we don't bother to handle that specially as the one user of this
+ * value calls dirname() anyway.
+ * TODO(geofft): Consider using PROCMAP_QUERY if supported.
+ */
+ uintptr_t low, high;
+ char filename[PATH_MAX];
+ while (fscanf(maps, "%lx-%lx %*s %*s %*s %*s %[^\n]", &low, &high, filename) == 3) {
+ if (low <= (uintptr_t)target && (uintptr_t)target < high) {
+ if (filename[0] == '/') {
+ return decode_to_dict(dict, key, filename);
+ }
+ break;
+ }
+ }
+ }
+#endif
+
#if HAVE_DLADDR
Dl_info libpython_info;
- if (dladdr(&Py_Initialize, &libpython_info) && libpython_info.dli_fname) {
+ if (dladdr(target, &libpython_info) && libpython_info.dli_fname) {
return decode_to_dict(dict, key, libpython_info.dli_fname);
}
-#endif
#endif

return PyDict_SetItemString(dict, key, Py_None) == 0;
diff --git a/Modules/getpath.py b/Modules/getpath.py
index b89d7427e3f..8c431e53be2 100644
--- a/Modules/getpath.py
+++ b/Modules/getpath.py
@@ -436,7 +436,7 @@ def search_up(prefix, *landmarks, test=isfile):

if not executable_dir and os_name == 'darwin' and library:
# QUIRK: macOS checks adjacent to its library early
- library_dir = dirname(library)
+ library_dir = dirname(dirname(library))
if any(isfile(joinpath(library_dir, p)) for p in STDLIB_LANDMARKS):
# Exceptions here should abort the whole process (to match
# previous behavior)
@@ -570,7 +570,7 @@ def search_up(prefix, *landmarks, test=isfile):

# First try to detect prefix by looking alongside our runtime library, if known
if library and not prefix:
- library_dir = dirname(library)
+ library_dir = dirname(dirname(library))
if ZIP_LANDMARK:
if os_name == 'nt':
# QUIRK: Windows does not search up for ZIP file
--
2.50.1 (Apple Git-155)