PHP 8.3 JIT tracing — recurring crash at theme.php:325 (4GB allocation)

Dear community,
I’ve been dealing with a recurring production crash for over a week that takes down the entire site for 1–2 minutes at a time. After extensive debugging I’ve narrowed it down to what appears to be a PHP 8.3 JIT issue, but I’d like to hear if anyone else has encountered this. Here’s what we found:


Environment

  • Trellis (latest), Bedrock, WordPress 6.8.3, PHP 8.3.28
  • Ubuntu 24.04, Nginx, 4 vCPUs, 16GB RAM
  • No persistent object cache, single site
  • ACF Pro 6.6.0 (via private Composer repo)
  • vinkla/extended-acf 14.0.0

The crash

All PHP-FPM workers crash simultaneously with:
PHP Fatal error: Allowed memory size of 536870912 bytes exhausted
(tried to allocate 4295229440 bytes) in wp-includes/theme.php on line 325
The allocation size (0x100040000 = 2^32 + 256KB) is always identical.
Site self-recovers after 1–2 minutes via Monit noticing and restarting PHP-FPM
Started March 10, escalated to 5 incidents/day by March 17.

What we investigated and ruled out

  • wp_options / autoloaded options: 152 options, 42KB total — not the cause
  • ACF options data: Largest option value: 603 bytes — not the cause
  • System memory / OOM killer: 15GB available, no OOM events
  • Custom filters on template hook: None
  • Specific URL trigger: All URLs affected equally during crash
  • OPcache shared memory: Healthy during crash — cache not full, no oom_restarts, plenty of free memory (verified via standalone diagnostic endpoint)

Key finding: standalone PHP works, WordPress doesn’t

We deployed a standalone opcache-diag.php (no WordPress bootstrap, localhost-only) that calls opcache_get_status(). During crashes, this endpoint succeeded through PHP-FPM with completely healthy OPcache stats. Only WordPress requests crashed. This ruled out OPcache shared memory corruption.

What we changed

  1. Interned strings buffer was exhausted

opcache.interned_strings_buffer was set to 8MB (Trellis default). Production had 8 bytes free. Increased to 32MB along with other OPcache settings:

php_opcache_interned_strings_buffer: 32
php_opcache_memory_consumption: 256
php_opcache_max_accelerated_files: 50000

Crash continued after this change.

  1. Disabled JIT

php_opcache_jit_buffer_size: 0

Crash stopped immediately. The crash was reproducible on demand by visiting ACF options pages (/wp/wp-admin/admin.php?page=global-settings) — not every time, but intermittently. After disabling JIT, no crashes so far.

Staging (same code, 1/2 hardware, minimal traffic) never reproduced the crash

Status: monitoring. It’s been hours, not days. We’re not yet certain JIT is the root cause vs. masking something else.

Related PHP bugs

  • php/php-src#16856 — Memory corruption with JIT
  • php/php-src#13817 — Segfault with JIT tracing
  • php/php-src#15497 — Crash with file_cache + JIT

Question

Anyone else experienced something like that on PHP 8.3.x with Trellis/Bedrock?

2 Likes

Thanks for reporting this! Made a PR to disable JIT by default:

Just wanted to drop a note and say thanks for sharing this.

I had issues with a site in a client’s AWS environment, of which we had no access… We could only deploy via trellis through a convoluted series of VPNs and tunnels. Don’t get me started on the back-and-forth required to get it provisioned initially. :person_facepalming:

I was never able to pin it down due to limited log access and the inability to work with the client in general, but you’re describing pretty much exactly what we experienced.

The fact you were able to pinpoint this to JIT is amazing.

1 Like