Skip to content
Merged
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
21 changes: 21 additions & 0 deletions cpython-unix/build-cpython.sh
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,27 @@ if [ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]; then
CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_func_explicit_bzero=no"
fi

# The modern UAPI overlay provides the memfd constants, but some glibc sysroots
# predate the memfd_create() wrapper. Force the configure check on and weak-link
# the wrapper so the function is exposed only when runtime glibc provides it.
# This workaround is specific to glibc builds; the UAPI overlay itself can also
# be used with other Linux libcs.
if [[ -n "${LINUX_UAPI_INCLUDE_ARCH:-}" && "${TARGET_TRIPLE}" == *-linux-gnu* ]]; then
if [[ -n "${PYTHON_MEETS_MINIMUM_VERSION_3_14}" ]]; then
patch -p1 -i "${ROOT}/patch-posixmodule-memfd-create-weak.patch"
else
patch -p1 -i "${ROOT}/patch-posixmodule-memfd-create-weak-3.13.patch"
fi

# Python 3.10 checks for memfd_create with a custom compile test instead
# of the cached ac_cv_func_memfd_create check used by newer versions.
if [[ -n "${PYTHON_MEETS_MAXIMUM_VERSION_3_10}" ]]; then
patch -p1 -i "${ROOT}/patch-configure-memfd-create-3.10.patch"
fi

CONFIGURE_FLAGS="${CONFIGURE_FLAGS} ac_cv_func_memfd_create=yes"
fi

# Define the base PGO profiling task, which we'll extend below with ignores
export PROFILE_TASK='-m test --pgo'

Expand Down
22 changes: 22 additions & 0 deletions cpython-unix/patch-configure-memfd-create-3.10.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -3822,6 +3822,10 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <mach-o/dyld.h>]], [[void *x=_dyl
])

AC_MSG_CHECKING(for memfd_create)
+if test "$ac_cv_func_memfd_create" = yes; then
+ AC_DEFINE(HAVE_MEMFD_CREATE, 1, Define if you have the 'memfd_create' function.)
+ AC_MSG_RESULT(yes)
+else
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
@@ -3834,6 +3838,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
AC_MSG_RESULT(yes)],
[AC_MSG_RESULT(no)
])
+fi

AC_MSG_CHECKING(for eventfd)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
35 changes: 35 additions & 0 deletions cpython-unix/patch-posixmodule-memfd-create-weak-3.13.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -528,6 +528,12 @@ extern char *ctermid_r(char *);
# include <linux/memfd.h>
#endif

+#ifdef HAVE_MEMFD_CREATE
+/* Weak references. */
+__attribute__((weak))
+int memfd_create(const char *name, unsigned int flags);
+#endif
+
/* eventfd() */
#ifdef HAVE_SYS_EVENTFD_H
# include <sys/eventfd.h>
@@ -15718,6 +15724,18 @@ posixmodule_exec(PyObject *m)
{
_posixstate *state = get_posix_state(m);

+#ifdef HAVE_MEMFD_CREATE
+ if (memfd_create == NULL) {
+ PyObject *dict = PyModule_GetDict(m);
+ if (dict == NULL) {
+ return -1;
+ }
+ if (PyDict_DelItemString(dict, "memfd_create") < 0) {
+ return -1;
+ }
+ }
+#endif
+
#if defined(HAVE_PWRITEV)
if (HAVE_PWRITEV_RUNTIME) {} else {
PyObject* dct = PyModule_GetDict(m);
35 changes: 35 additions & 0 deletions cpython-unix/patch-posixmodule-memfd-create-weak.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -192,6 +192,12 @@
# include <linux/memfd.h> // memfd_create(), MFD_CLOEXEC
#endif

+#ifdef HAVE_MEMFD_CREATE
+/* Weak references. */
+__attribute__((weak))
+int memfd_create(const char *name, unsigned int flags);
+#endif
+
#ifdef HAVE_SYS_EVENTFD_H
# include <sys/eventfd.h> // eventfd()
#endif
@@ -18128,6 +18134,18 @@ posixmodule_exec(PyObject *m)
{
_posixstate *state = get_posix_state(m);

+#ifdef HAVE_MEMFD_CREATE
+ if (memfd_create == NULL) {
+ PyObject *dict = PyModule_GetDict(m);
+ if (dict == NULL) {
+ return -1;
+ }
+ if (PyDict_PopString(dict, "memfd_create", NULL) < 0) {
+ return -1;
+ }
+ }
+#endif
+
#if defined(HAVE_PWRITEV)
if (HAVE_PWRITEV_RUNTIME) {} else {
PyObject* dct = PyModule_GetDict(m);
29 changes: 29 additions & 0 deletions pythonbuild/disttests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,35 @@ def test_socket_af_vsock(self):
def test_os_pidfd_open(self):
self.assertTrue(hasattr(os, "pidfd_open"))

@unittest.skipUnless(
"-linux-gnu" in os.environ["TARGET_TRIPLE"],
"memfd_create weak linking is enabled for Linux GNU targets",
)
def test_os_memfd_create(self):
import ctypes
import errno

libc = ctypes.CDLL(None)
libc_has_memfd_create = hasattr(libc, "memfd_create")
self.assertEqual(hasattr(os, "memfd_create"), libc_has_memfd_create)

if not libc_has_memfd_create:
return

try:
fd = os.memfd_create("python-build-standalone-test")
except OSError as exc:
if exc.errno == errno.ENOSYS:
self.skipTest("the runtime kernel does not support memfd_create")
raise

try:
os.write(fd, b"memfd_create")
os.lseek(fd, 0, os.SEEK_SET)
self.assertEqual(os.read(fd, 12), b"memfd_create")
finally:
os.close(fd)

def test_linux_uapi_not_in_sysconfig(self):
import sysconfig

Expand Down
Loading