Skip to content

Fix: Reset PHP OPcache after update to prevent 500 errors#1288

Open
Sebbeben wants to merge 1 commit intoPart-DB:masterfrom
Sebbeben:fix/opcache-reset-after-update
Open

Fix: Reset PHP OPcache after update to prevent 500 errors#1288
Sebbeben wants to merge 1 commit intoPart-DB:masterfrom
Sebbeben:fix/opcache-reset-after-update

Conversation

@Sebbeben
Copy link
Contributor

@Sebbeben Sebbeben commented Mar 5, 2026

Problem

After the update manager completes an update (git checkout, composer install, cache clear/warmup), PHP-FPM may still serve stale bytecode from OPcache. This causes 500 errors when the progress page auto-refreshes, because the old cached container tries to instantiate classes with changed constructor signatures.

Example error seen after updating from v2.7.1 to v2.8.1:

AttachmentURLGenerator::__construct(), 6 passed... and exactly 7 expected

This affects any native git installation running PHP-FPM with OPcache enabled (which is the default and recommended configuration).

Solution

Added an OPcache reset step after cache warmup in the update, restore, and rollback flows. The approach:

  1. Creates a temporary PHP script with a random token filename in public/ (e.g., _opcache_reset_<random>.php)
  2. Invokes it via HTTP (http://127.0.0.1/ then http://localhost/) to trigger opcache_reset() in the PHP-FPM context
  3. The script self-deletes after execution, with a safety cleanup in the finally block
  4. If HTTP invocation fails (e.g., non-standard web server setup), it logs a warning and continues gracefully

Why this approach?

  • opcache_reset() from CLI only affects the CLI process, not PHP-FPM
  • Restarting PHP-FPM requires root/sudo privileges
  • External tools like cachetool may not be installed
  • The temporary HTTP script approach is the most portable solution

Changes

  • src/Services/System/UpdateExecutor.php:
    • Added resetOpcache() private method
    • Added OPcache reset as Step 13 in the update flow (between cache warmup and maintenance mode off)
    • Added OPcache reset in the restore flow
    • Added OPcache reset after rollback
    • Updated total step counts accordingly

After cache warmup, create a temporary PHP script in the public
directory and invoke it via HTTP to reset OPcache in the PHP-FPM
context. This prevents stale bytecode from causing 500 errors when
the progress page refreshes after code has been updated.

The reset is also performed after rollback and during restore.
Uses a random token in the filename for security, and the script
self-deletes after execution with a cleanup in the finally block.
@codecov
Copy link

codecov bot commented Mar 5, 2026

Codecov Report

❌ Patch coverage is 0% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.31%. Comparing base (32a666f) to head (a4c1e00).
⚠️ Report is 16 commits behind head on master.

Files with missing lines Patch % Lines
src/Services/System/UpdateExecutor.php 0.00% 49 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #1288      +/-   ##
============================================
- Coverage     55.42%   55.31%   -0.12%     
- Complexity     8266     8277      +11     
============================================
  Files           610      610              
  Lines         26513    26566      +53     
============================================
  Hits          14694    14694              
- Misses        11819    11872      +53     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant