Skip to content

Keep the shared opcode cache from changing what the code does - #417

Merged
schlessera merged 2 commits into
mainfrom
fix/php-tuning-opcache
Nov 2, 2026
Merged

schlessera merged 2 commits into
mainfrom
fix/php-tuning-opcache

Conversation

@schlessera

@schlessera schlessera commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

Fixes #416, a regression from #401 in 5.4.0.

Disabled functions

With the PHP settings of #401, the WP-CLI processes share a file-based opcode cache. The optimizer evaluates some calls at compile time, among them function_exists() (optimizer pass 1, and others). WP-CLI defines a fallback ini_set() in php/fallback-functions.php behind ! function_exists( 'ini_set' ). Compiled in a process with the default settings, that condition is folded to false and the fallback is gone from the cached code. A later process with -ddisable_functions=ini_set gets the cached code and fails with:

Call to undefined function WP_CLI\ini_set() in php/WP_CLI/Runner.php:3112

Reproduced by running wp cli version and then WP_CLI_PHP_ARGS='-ddisable_functions=ini_set' wp cli info. It fails with any optimization level that includes pass 1, and with pass 1 alone, and passes with opcache.optimization_level=0.

The cache now stores unoptimized code, so it only saves parsing and compiling, and the code does what it does without opcache, which is how the CLI runs by default. The suite of this package takes the same time either way (11 s with 4 workers, warm).

Scan directory after a restart without Xdebug

Behat (and Composer) restart without Xdebug through composer/xdebug-handler, which sets PHP_INI_SCAN_DIR to an empty string in the restarted process. The tuning then passed only its own directory to the WP-CLI processes, which lost the scan directory of the system and every extension configured there (all of them on Debian and Ubuntu). The original directories are now taken from XDEBUG_HANDLER_SETTINGS.

SQLite option

As pointed out on #415, SQLITE_ENABLE_UPDATE_DELETE_LIMIT needs a parser generated from the canonical sources, which the amalgamation does not have, so the option is left out.

Testing

  • New scenario in features/testing.feature that runs WP-CLI normally and then with ini_set disabled. It fails on main with the error above and passes with this change.
  • wp-cli/wp-cli features/bootstrap.feature:506 and features/utils.feature:108 pass with this change and fail with 5.4.1.
  • A scenario printing PHP_INI_SCAN_DIR gets /etc/php/conf.d:/tmp/wp-cli-test-php-config instead of only /tmp/wp-cli-test-php-config.

Summary by CodeRabbit

  • Tests
    • Added coverage confirming that cli info succeeds and reports the PHP binary when ini_set is disabled. The scenario is skipped on Windows.
    • Expanded checks around PHP configuration handling, including opcode-cache settings and custom scan-directory values.
  • Build
    • Updated SQLite build configuration by removing one compile-time option. Other compile flags remain unchanged.

The optimizer evaluates calls like function_exists() at compile time, so code cached
by a process with the default settings skipped the ini_set() fallback of WP-CLI in a
process that disables it. Cache the code without optimizing it.

Behat and Composer restart without Xdebug, which clears PHP_INI_SCAN_DIR, so the
WP-CLI processes lost the scan directory of the system, and the extensions configured
there. Take the original directories from the restart settings instead.

Also leave out SQLITE_ENABLE_UPDATE_DELETE_LIMIT, which needs a parser the
amalgamation does not have.

Fixes #416.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@schlessera
schlessera requested a review from a team as a code owner November 2, 2026 08:44
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 51 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: f025702c-d82b-4d34-af10-b66227c61227
Commits

Reviewing files that changed from the base of the PR and between 7d12115 and 87d1bf1.

Files selected for processing: 1
  • src/Context/FeatureContext.php
Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c6781e7c-fcbf-4506-bdce-00324f0108bd
Commits

Reviewing files that changed from the base of the PR and between e4e99fc and 7d12115.

Files selected for processing: 3
  • features/testing.feature
  • src/Context/FeatureContext.php
  • utils/docker/Dockerfile

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The changes update generated PHP settings and add a scenario that runs cli info with ini_set disabled. They also remove a compile flag from the SQLite Docker build.

Changes: PHP settings regression coverage

Layer / File(s) Summary
PHP settings and regression scenario
src/Context/FeatureContext.php, features/testing.feature
Generated PHP settings now set opcache.optimization_level=0 and restore the scan-directory setting from XDEBUG_HANDLER_SETTINGS when applicable. A Windows-skipped scenario checks cli info with ini_set disabled.

SQLite build configuration

Layer / File(s) Summary
SQLite compile flags
utils/docker/Dockerfile
The build no longer defines SQLITE_ENABLE_UPDATE_DELETE_LIMIT when compiling the older system SQLite version.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • wp-cli/wp-cli-tests#413: Adds the conditional SQLite source build and its compile flags, which this change also updates.
  • wp-cli/wp-cli-tests#415: Adds SQLite compile-time features to the Docker build, including the flag removed here.

Suggested labels: bug, scope:testing, scope:distribution, scope:artifacts

Suggested reviewers: swissspidy, mrsdizzie

Merge Risk: Moderate · previous review 7d121

The fix for the ini_set failure can be defeated on machines that already hold optimized cache entries from 5.4.0, because the cache directory is never versioned or cleared. Restoring the scan directory without PHPRC can also produce duplicate-extension warnings that fail test steps in some environments. Version the cache and config directories and restore PHPRC before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Out of Scope Changes check Warning The SQLITE_ENABLE_UPDATE_DELETE_LIMIT removal from utils/docker/Dockerfile does not implement or test issue #416. The PR description attributes this change to issue #415. The PHP_INI_SCAN_DIR re… Remove the unrelated SQLITE_ENABLE_UPDATE_DELETE_LIMIT change from this pull request, or link a coding issue that requires the SQLite build change and assess it as separate scope.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly describes the primary change: preventing the shared opcode cache from altering behavior. It is concise and directly related to the reported regression.
Linked Issues check Passed Issue #416 requires WP-CLI scenarios with -ddisable_functions=ini_set to stop failing. The new scenario in features/testing.feature first runs wp cli version, then runs cli info with ini_set…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Full details: Linked Issues check

Explanation

Issue #416 requires WP-CLI scenarios with -ddisable_functions=ini_set to stop failing. The new scenario in features/testing.feature first runs wp cli version, then runs cli info with ini_set disabled and requires return code 0. FeatureContext::get_php_tuning_env_variables() sets opcache.optimization_level=0, which prevents the shared cache from storing optimized code that removes the fallback. The supplied validation reports that the scenario passes with this change.

Full details: Docstring Coverage

Explanation

Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 1 files. (2 skipped: 2 unsupported.)

Full details: Out of Scope Changes check

Explanation

The SQLITE_ENABLE_UPDATE_DELETE_LIMIT removal from utils/docker/Dockerfile does not implement or test issue #416. The PR description attributes this change to issue #415. The PHP_INI_SCAN_DIR restoration supports the test-process environment and is related to the test harness, but the SQLite build change has no demonstrated connection to the linked issue.

Resolution

Remove the unrelated SQLITE_ENABLE_UPDATE_DELETE_LIMIT change from this pull request, or link a coding issue that requires the SQLite build change and assess it as separate scope.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@github-actions github-actions Bot added bug Something isn't working scope:testing Related to testing labels Nov 2, 2026
@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 18 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/Context/FeatureContext.php 0.00% 18 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread src/Context/FeatureContext.php Resolved
Comment thread src/Context/FeatureContext.php Resolved
Comment thread src/Context/FeatureContext.php Resolved
A cache directory written by 5.4.0 holds optimized code, which opcache keeps using,
and an older suite running at the same time would rewrite the configuration file.
Name both directories after the settings, so that each set has its own.

After a restart without Xdebug, PHPRC points to a configuration file that holds the
scanned files already, which loaded them twice when it reached the WP-CLI processes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@schlessera
schlessera merged commit 035668f into main Nov 2, 2026
65 of 66 checks passed
@schlessera
schlessera deleted the fix/php-tuning-opcache branch November 2, 2026 09:00
@schlessera schlessera added this to the 5.4.2 milestone Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working scope:testing Related to testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Scenarios that disable ini_set fail since 5.4.0

1 participant