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.

Closes GH-10589.
This commit is contained in:
Max Kellermann 2023-02-14 17:54:04 +01:00 committed by David Carlier
parent ab99072608
commit e9c8621632
3 changed files with 22 additions and 1 deletions

2
NEWS
View File

@ -77,6 +77,8 @@ PHP NEWS
(Arnaud)
. Allows W/X bits on page creation on FreeBSD despite system settings.
(David Carlier)
. Added memfd api usage, on Linux, for zend_shared_alloc_create_lock()
to create an abstract anonymous file for the opcache's lock. (Max Kellermann)
- PCNTL:
. SA_ONSTACK is now set for pcntl_signal. (Kévin Dunglas)

View File

@ -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([[

View File

@ -19,6 +19,13 @@
+----------------------------------------------------------------------+
*/
#if defined(__linux__) && defined(HAVE_MEMFD_CREATE)
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# include <sys/mman.h>
#endif
#include <errno.h>
#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) {