Native PHP on Windows: one of the 4 workers crashes on cold start (exit 3221225477), site shows "PHP error during startup"

Open
#4,886 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
nodejs, php
Domain
backend, desktop

Research direction

Inspect php-server-child.mjs and getDefaultPhpArgs, then trace the parallel warm-up in waitForServerReady. Run the Windows native PHP reproduction with four workers and a cold opcache.file_cache; done means the site starts reliably without worker crashes while retaining acceptable opcache behavior.

Written by the indexing model from the issue text.

Description

Quick summary

On Windows, one of my sites fails to start every single time since yesterday. Studio shows "PHP Error Detected / PHP error during startup" but there is no PHP error in the site. The daemon log shows one of the 4 native PHP workers dying with exit code 3221225477 (that's 0xC0000005, access violation) right after the first warm-up request.

I dug into it and it looks like a race on the opcache file cache. Studio starts all 4 workers with the same -d opcache.file_cache= and then hits all 4 at once. On a cold cache they all write and read the same cache files at the same moment and 1 to 3 of them segfault. Only my biggest site (most PHP files) hits it, smaller sites start fine. Same crash with PHP 8.2 and 8.4

Steps to reproduce

Through Studio:

  1. Windows 11, Studio 1.21.0, native PHP runtime, PHP 8.4 (also 8.2).
  2. A site with a fair amount of PHP: custom theme + ACF Pro + WP Search with Algolia + a custom plugin. WP 7.1.
  3. studio start
  4. Open the site. "PHP error during startup" page. Daemon log:
    [PHP Server] PHP worker 1/4 exited unexpectedly (code: 3221225477, signal: null)
    (worker number changes each time, 8 out of 8 starts failed)

Outside Studio, same thing with just php -S, which is how I narrowed it down:

  1. From the site folder, start 4 workers the way Studio does (same php.exe, same php.ini, same router.php, same prepend file, empty cache dir):
    for each port 9123..9126:
    php.exe -c -d "opcache.file_cache=" -d "auto_prepend_file=" -S 127.0.0.1:
  2. Hit all 4 at the same time with node (this is what waitForServerReady does):
    const ports = [9123, 9124, 9125, 9126];
    await Promise.all(ports.map(p => fetch(http://127.0.0.1:${p}/, { redirect: "manual" }).then(r => console.log(p, r.status)).catch(e => console.log(p, "ERR", e.cause?.code))));
  3. 1 to 3 of the 4 processes die with a segfault, the fetches get ECONNRESET.

Notes from testing:

  • Sequential curl to the 4 workers does not trigger it, only parallel requests on a cold cache.
  • 1 worker alone never crashes, even in file_cache_only mode with repeated requests.
  • opcache on, no file_cache: 0 crashes (3 runs)
  • opcache fully off: 0 crashes
  • file_cache + file_cache_fallback=0: still crashes
  • file_cache + file_cache_consistency_checks=1: still crashes
  • Same result on the 8.2.33 and 8.4.24 Studio binaries.
  • A site with less code (other Studio site on the same machine) starts fine every time, so it's timing, not a specific file.
What you expected to happen

Site starts. It has no PHP errors: php -l is clean, studio wp eval loads WordPress with all plugins and theme, and a single php -S serves the homepage with 200.

What actually happened

One worker crashes on the warm-up request, Studio kills the pool and shows "PHP Error Detected / PHP error during startup". No PHP error is ever printed anywhere. Only the exit code in the daemon log.

App or CLI?

Both

Version

1.21.0

Impact

One

Available workarounds?

Yes, easy to implement

Platform

Windows

Architecture

x64 (Intel, AMD)

Logs or notes

Daemon log (~/.studio/daemon/logs/studio-site--error-.log):
[PHP Server] PHP worker 4/4 exited unexpectedly (code: 3221225477, signal: null)
[PHP Server] PHP worker 3/4 exited unexpectedly (code: 3221225477, signal: null)
[PHP Server] PHP worker 1/4 exited unexpectedly (code: 3221225477, signal: null)
[PHP Server] PHP worker 2/4 exited unexpectedly (code: 3221225477, signal: null)
Each one is about 3 seconds after "Accepted" on the first request, nothing else logged.

Environment: Windows 11 Pro 10.0.26200, Studio 1.21.0, native PHP 8.4.24 (php-bin/8.4.24-studio-2), also 8.2.33, WP 7.1, xdebug off, file access "All files".

Workaround I'm using: ini_set('opcache.enable', '0'); at the top of wp-config.php. That stops the cache writes after the first few files and the site has started clean every time since (3/3 restarts). Pages are 2 to 3x slower without opcache though, so not great long term.

Ideas for a real fix, whichever is easier on your side:

  • warm up the workers one at a time instead of all 4 in parallel, so the first one fills the cache and the others just read it
  • or give each worker its own opcache.file_cache dir
  • or don't set opcache.file_cache at all (shared memory opcache alone was stable in my tests)

The worker count and file_cache are hardcoded in php-server-child.mjs / getDefaultPhpArgs, so there is nothing a user can change apart from turning opcache off.

Dominant language
TypeScript
Stars
523
Forks
99
Avg merge
1d 18h
Merged PRs (30d)
167

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Automattic/studio

All issues in Automattic/studio

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.