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) {