Edit report at https://bugs.php.net/bug.php?id=77260&edit=1
ID: 77260
Updated by: nikic@php.net
Reported by: ettore at themecraft dot studio
Summary: preg_match_all(): JIT compilation failed: no more
memory
Status: Assigned
Type: Bug
Package: PCRE related
Operating System: macOS 10.13.6
PHP Version: 7.3.0
Assigned To: nikic
Block user comment: N
Private report: N
New Comment:
Relevant discussion: https://bugs.exim.org/show_bug.cgi?id=2334
Unfortunately there's still the issue with MAP_JIT and fork() being incompatible, leading to
the issue mentioned by sbarex at gmail dot com. It doesn't look like progress on avoiding that
issue has been made.
Previous Comments:
------------------------------------------------------------------------
[2019-09-17 21:28:03] nikic@php.net
I'm afraid that this bug report has ended up as a meta-issues for all kinds of mmap failures in
pcre jit, which may not all have the same root cause.
I think the original problem and what is affecting macOS users is the fact that PCRE2 has introduced
use of MAP_JIT to be compatible with macOS 10.14. However, MAP_JIT is badly broken on macOS 10.13.
We need to backport the following diff from PCRE2 10.33 to the 7.3 branch:
diff --git a/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c
b/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c
index 7c18578618cf..3b37a9751f81 100644
--- a/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c
+++ b/ext/pcre/pcre2lib/sljit/sljitExecAllocator.c
@@ -94,6 +94,46 @@ static SLJIT_INLINE void free_chunk(void *chunk, sljit_uw size)
#else
+#ifdef __APPLE__
+/* Configures TARGET_OS_OSX when appropriate */
+#include <TargetConditionals.h>
+
+#if TARGET_OS_OSX && defined(MAP_JIT)
+#include <sys/utsname.h>
+#endif /* TARGET_OS_OSX && MAP_JIT */
+
+#ifdef MAP_JIT
+
+static SLJIT_INLINE int get_map_jit_flag()
+{
+#if TARGET_OS_OSX
+ /* On macOS systems, returns MAP_JIT if it is defined _and_ we're running on a version
+ of macOS where it's OK to have more than one JIT block. On non-macOS systems, returns
+ MAP_JIT if it is defined. */
+ static int map_jit_flag = -1;
+
+ /* The following code is thread safe because multiple initialization
+ sets map_jit_flag to the same value and the code has no side-effects.
+ Changing the kernel version witout system restart is (very) unlikely. */
+ if (map_jit_flag == -1) {
+ struct utsname name;
+
+ uname(&name);
+
+ /* Kernel version for 10.14.0 (Mojave) */
+ map_jit_flag = (atoi(name.release) >= 18) ? MAP_JIT : 0;
+ }
+
+ return map_jit_flag;
+#else /* !TARGET_OS_OSX */
+ return MAP_JIT;
+#endif /* TARGET_OS_OSX */
+}
+
+#endif /* MAP_JIT */
+
+#endif /* __APPLE__ */
+
static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
{
void *retval;
@@ -103,17 +143,17 @@ static SLJIT_INLINE void* alloc_chunk(sljit_uw size)
int flags = MAP_PRIVATE | MAP_ANON;
#ifdef MAP_JIT
- flags |= MAP_JIT;
+ flags |= get_map_jit_flag();
#endif
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, flags, -1, 0);
-#else
+#else /* !MAP_ANON */
if (dev_zero < 0) {
if (open_dev_zero())
return NULL;
}
retval = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, dev_zero, 0);
-#endif
+#endif /* MAP_ANON */
return (retval != MAP_FAILED) ? retval : NULL;
}
------------------------------------------------------------------------
[2019-09-17 20:38:34] robertwildling at gmail dot com
I work with TYPO3. In the course of updating older versions, this same exact error happened to me,
too. Turning of pcre_jit is no option, because TYPO3 won't work then. So I moved down to php
7.2.22. The interesting thing is that the error logger of TYPO3 catches the same preg* errors, too,
but the system does not crash.
I am also on macos HighSierra with a brew installation.
------------------------------------------------------------------------
[2019-07-31 19:05:58] funky99 at gmx dot de
I came accross this problem as we switched an internal apllication from PHP 7.0.32 to 7.3.6 (both
FPM) on our Gentoo based Managed webserver.
I excpected no or at least a slight increase in performance, but the opposite happened.
I.e. on a rather small page, runtime changed from 20ms (7.0) to 40ms (7.3). On bigger pages
it's worse.
I checked the PHP errors and saw a couple of "preg*: JIT compilation failed: no more
memory" errors, directly after the restart of the FPM processes.
We are using an rather old framework which works a lot with preg* functions for the template engine.
If I set pcre.jit = 0 performance in PHP 7.0 gets also down to 40ms.
As erik at coretech dot se mentioned it might have to do with SELinux. But it's the same
machine and same Linux kernel, so if the problem is because of SELinux or other security feeatures,
shouldn't it not work on PHP 7.0 as well? (I'm not a Linux expert)
So I it may be a bug which should have been fixed for PHP 7.3 (I has the same same problems for PHP
7.1. and 7.2).
------------------------------------------------------------------------
[2019-07-14 10:07:45] mc12345678 at mc12345678 dot com
Working with Zen Cart, most recently the development version 1.5.7 available from https://github.com/zencart/zencart. With the
following server characteristics:
Server OS: Linux 4.14.117-grsec-grsec+
Server Date: 07/14/2019 02:03:38
Server Up Time: 02:03:38 up 6 days, 18:52, 0 users, load average: 3.28, 3.85, 3.73
HTTP Server: Apache
PHP Version: 7.3.6 (Zend: 3.3.6)
PHP File Uploads: On
Upload Max Size: 2M
PHP Memory Limit: 512M
POST Max Size: 8M
Database Engine: MySQL 5.7.25-log
Database Date: 07/14/2019 02:03:38
Database Data Size: 458 kB
Database Index Size: 559 kB
MySQL Slow Query Log Status: On
MySQL Slow Query Log File: /dh/mysql/logs/mysql.leberman.slow
MySQL Mode: NO_ENGINE_SUBSTITUTION
Software is ableto use a few instances of a preg_xxxx function, but then appears to run out of
memory. Increasing the memory limit has had no positive impact on the generation of warning
messages. So far other than potentially substituting another filter type method (strstr, strops,
etc...), the only successful way of preventing the warnings has been some php.ini related
disablement of jcre.jit 0 either directly in the php.ini (affecting all code that executes that
php.ini file) or from within using '@ini_set("pcre.jit", "0");'. A
suggestion has been made to disable using .htaccess; however, this particular software product does
not use a base .htaccess file. The recommended coding was: 'php_value pcre.jit 0'.
Someone using the same software on a Macintosh was able to operate without any such additional
action. Discussion is provided here: https://github.com/zencart/zencart/pull/2537
------------------------------------------------------------------------
[2019-06-20 18:45:11] self at danpock dot me
@erik, what do you think the issue on Mac OS is then? AFAIK, Mac doesn't have SE Linux - though
I'm unsure if it has something similar?
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=77260
--
Edit this bug report at https://bugs.php.net/bug.php?id=77260&edit=1