From 211017a4641ef56629a0bc52b8925d3951be96f9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 14 Feb 2023 17:54:04 +0100 Subject: [PATCH] ext/opcache/zend_shared_alloc: use memfd for locking if available A memfd is a virtual file that has no reachable path, therefore does not clobber any filesystem. It is deleted automatically as soon as the last handle gets closed. The feature is available since Linux kernel 3.17. --- ext/opcache/config.m4 | 2 +- ext/opcache/zend_shared_alloc.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 2a83fa2455974..7e681bb112815 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -105,7 +105,7 @@ if test "$PHP_OPCACHE" != "no"; then fi - AC_CHECK_FUNCS([mprotect]) + AC_CHECK_FUNCS([mprotect memfd_create]) AC_MSG_CHECKING(for sysvipc shared memory support) AC_RUN_IFELSE([AC_LANG_SOURCE([[ diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index f32f8c46eae48..5f92c150e957d 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -19,6 +19,13 @@ +----------------------------------------------------------------------+ */ +#if defined(__linux__) && defined(HAVE_MEMFD_CREATE) +# ifndef _GNU_SOURCE +# define _GNU_SOURCE +# endif +# include +#endif + #include #include "ZendAccelerator.h" #include "zend_shared_alloc.h" @@ -81,6 +88,18 @@ void zend_shared_alloc_create_lock(char *lockfile_path) zts_lock = tsrm_mutex_alloc(); #endif +#if defined(__linux__) && defined(HAVE_MEMFD_CREATE) + /* on Linux, we can use a memfd instead of a "real" file, so + * we can do this without a writable filesystem and without + * needing to clean up */ + /* note: FreeBSD has memfd_create(), too, but fcntl(F_SETLKW) + * on it fails with EBADF, therefore we use this only on + * Linux */ + lock_file = memfd_create("opcache_lock", MFD_CLOEXEC); + if (lock_file >= 0) + return; +#endif + snprintf(lockfile_name, sizeof(lockfile_name), "%s/%sXXXXXX", lockfile_path, SEM_FILENAME_PREFIX); lock_file = mkstemp(lockfile_name); if (lock_file == -1) {