From 8ddb452214a71150c858926ee94c417aae9732aa Mon Sep 17 00:00:00 2001 From: Dennis Camera Date: Sun, 19 Apr 2026 17:11:57 +0000 Subject: [PATCH] Detect availability of PR_SET_VMA at runtime (fixes build with musl libc) The build would fail on musl-based systems with the following error: gcc -c -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -std=c11 -Wextra -Wno-unused-parameter -Wno-missing-field-initializers -Wstrict-prototypes -Werror=implicit-function-declaration -fvisibility=hidden -I./Include/internal -I./Include/internal/mimalloc -I. -I./Include -DPy_BUILD_CORE -o Objects/obmalloc.o Objects/obmalloc.c In file included from ./Include/internal/pycore_mmap.h:16, from Objects/obmalloc.c:5: /usr/include/sys/prctl.h:88:8: error: redefinition of 'struct prctl_mm_map' 88 | struct prctl_mm_map { | ^~~~~~~~~~~~ In file included from ./Include/internal/pycore_mmap.h:15: /usr/include/linux/prctl.h:134:8: note: originally defined here 134 | struct prctl_mm_map { | ^~~~~~~~~~~~ make: *** [Makefile:3388: Objects/obmalloc.o] Error 1 This is due to Python including both and (which on glibc imports the definitions from and on musl includes all the definitions itself). Given that Python is not the Linux kernel, should be included. Another issue of the previous implementation and the configure check was that the `_PyAnnotateMemoryMap()` function would only be enabled if the linux-headers on the build host are recent enough to contain the `PR_SET_VMA_ANON_NAME` macro. However the resulting binaries might be run on older kernels lacking the functionality or be built on older systems but run on newer kernels. With this patch, the function is always enabled and the magic numbers are included with Python, so that the `prctl()` is always executed and feature detection is essentially done at runtime. When run on a kernel too old to support `PR_SET_VMA_ANON_NAME`, `mmap.mmap.set_name()` will silently do nothing. When the kernel is new enough but `CONFIG_ANON_VMA_NAME` is not enabled, `mmap.mmap.set_name()` will raise an `OSError`, e.g.: >>> mm.set_name("hello") Traceback (most recent call last): File "", line 1, in mm.set_name("hello") ~~~~~~~~~~~^^^^^^^^^ OSError: [Errno 22] Invalid argument --- Include/internal/pycore_mmap.h | 16 ++++++++++++---- configure | 24 ------------------------ configure.ac | 9 --------- pyconfig.h.in | 7 ------- 4 files changed, 12 insertions(+), 44 deletions(-) diff --git a/Include/internal/pycore_mmap.h b/Include/internal/pycore_mmap.h index 897816db01077f..63033e30c5cbee 100644 --- a/Include/internal/pycore_mmap.h +++ b/Include/internal/pycore_mmap.h @@ -11,12 +11,17 @@ extern "C" { #include "pycore_pystate.h" -#if defined(HAVE_PR_SET_VMA_ANON_NAME) && defined(__linux__) -# include -# include +#if defined(__linux__) + +#include + +#ifndef PR_SET_VMA +# define PR_SET_VMA 0x53564d41 +#endif +#ifndef PR_SET_VMA_ANON_NAME +# define PR_SET_VMA_ANON_NAME 0 #endif -#if defined(HAVE_PR_SET_VMA_ANON_NAME) && defined(__linux__) static inline int _PyAnnotateMemoryMap(void *addr, size_t size, const char *name) { @@ -33,12 +38,15 @@ _PyAnnotateMemoryMap(void *addr, size_t size, const char *name) } return 0; } + #else + static inline int _PyAnnotateMemoryMap(void *Py_UNUSED(addr), size_t Py_UNUSED(size), const char *Py_UNUSED(name)) { return 0; } + #endif #ifdef __cplusplus diff --git a/configure b/configure index 562bb6860c79a9..5236e420864350 100755 --- a/configure +++ b/configure @@ -24260,30 +24260,6 @@ printf "%s\n" "#define HAVE_UT_NAMESIZE 1" >>confdefs.h fi -# musl libc redefines struct prctl_mm_map and conflicts with linux/prctl.h -if test "$ac_cv_libc" != musl -then : - -ac_fn_check_decl "$LINENO" "PR_SET_VMA_ANON_NAME" "ac_cv_have_decl_PR_SET_VMA_ANON_NAME" "#include - #include -" "$ac_c_undeclared_builtin_options" "CFLAGS" -if test "x$ac_cv_have_decl_PR_SET_VMA_ANON_NAME" = xyes -then : - ac_have_decl=1 -else case e in #( - e) ac_have_decl=0 ;; -esac -fi -printf "%s\n" "#define HAVE_DECL_PR_SET_VMA_ANON_NAME $ac_have_decl" >>confdefs.h -if test $ac_have_decl = 1 -then : - -printf "%s\n" "#define HAVE_PR_SET_VMA_ANON_NAME 1" >>confdefs.h - -fi - - -fi # check for openpty, login_tty, and forkpty diff --git a/configure.ac b/configure.ac index 20e1afc2e9ee14..54e906bbb5aa8f 100644 --- a/configure.ac +++ b/configure.ac @@ -5728,15 +5728,6 @@ AC_CHECK_DECLS([UT_NAMESIZE], [Define if you have the 'HAVE_UT_NAMESIZE' constant.])], [], [@%:@include ]) -# musl libc redefines struct prctl_mm_map and conflicts with linux/prctl.h -AS_IF([test "$ac_cv_libc" != musl], [ -AC_CHECK_DECLS([PR_SET_VMA_ANON_NAME], - [AC_DEFINE([HAVE_PR_SET_VMA_ANON_NAME], [1], - [Define if you have the 'PR_SET_VMA_ANON_NAME' constant.])], - [], - [@%:@include - @%:@include ]) -]) # check for openpty, login_tty, and forkpty AC_CHECK_FUNCS([openpty], [], diff --git a/pyconfig.h.in b/pyconfig.h.in index 9da33c954a52f8..752376263acc48 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -224,10 +224,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DB_H -/* Define to 1 if you have the declaration of 'PR_SET_VMA_ANON_NAME', and to 0 - if you don't. */ -#undef HAVE_DECL_PR_SET_VMA_ANON_NAME - /* Define to 1 if you have the declaration of 'RTLD_DEEPBIND', and to 0 if you don't. */ #undef HAVE_DECL_RTLD_DEEPBIND @@ -1003,9 +999,6 @@ /* Define if your compiler supports function prototype */ #undef HAVE_PROTOTYPES -/* Define if you have the 'PR_SET_VMA_ANON_NAME' constant. */ -#undef HAVE_PR_SET_VMA_ANON_NAME - /* Define to 1 if you have the 'pthread_condattr_setclock' function. */ #undef HAVE_PTHREAD_CONDATTR_SETCLOCK