Skip to content

Restart process when pcov or tideways extension is loaded - #6757

Open
staabm wants to merge 14 commits into
phpstan:2.3.xfrom
staabm:reset
Open

staabm wants to merge 14 commits into
phpstan:2.3.xfrom
staabm:reset

Conversation

@staabm

@staabm staabm commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

based on the feedback on the xdebug-handler project, we can subclass the XdebugHandler and override a few methods to achieve restarting in a single go.

closes #6253
closes phpstan/phpstan#15407


➜  phpstan-src git:(reset) echo "<?php echo 'Hello world';" > test.php
➜  phpstan-src git:(reset) ✗ XDEBUG_HANDLER_DEBUG=1 bin/phpstan analyse test.php 
xdebug-handler[35332] Checking PHPSTAN_ALLOW_XDEBUG
xdebug-handler[35332] The Xdebug extension is not loaded
xdebug-handler[35332] Process restarting (PHPSTAN_ALLOW_XDEBUG=internal||1|*|*)
xdebug-handler[35332] Running: [/opt/homebrew/Cellar/php/8.5.11_1/bin/php, bin/phpstan, analyse, test.php]
xdebug-handler[35336] Checking PHPSTAN_ALLOW_XDEBUG
xdebug-handler[35336] Restarted (143 ms). The Xdebug extension is not loaded
Note: Using configuration file /Users/staabm/workspace/phpstan-src/phpstan.neon.dist.
 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [OK] No errors                                                                                                                                                                                                                            

xdebug-handler[35332] Restarted process exited 0

before this PR when pcov loaded+enabled

➜  phpstan-src git:(2.3.x) make phpstan
php bin/phpstan clear-result-cache -q && php -d memory_limit=450M bin/phpstan -v
Note: Using configuration file /Users/staabm/workspace/phpstan-src/phpstan.neon.dist.
 2790/2790 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% 16 secs

 [OK] No errors                                                                                                         

Elapsed time: 18.85 seconds
Peak memory: 380.52 MB (main process), 252 MB (largest of 14 forked workers)

after this PR when pcov loaded+enabled

➜  phpstan-src git:(reset) make phpstan 
php bin/phpstan clear-result-cache -q && php -d memory_limit=450M bin/phpstan -v
Note: Using configuration file /Users/staabm/workspace/phpstan-src/phpstan.neon.dist.
 2791/2791 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% 10 secs

 [OK] No errors                                                                                                         

Elapsed time: 12.62 seconds
Peak memory: 392.52 MB (main process), 248 MB (largest of 14 forked workers)

@staabm

staabm commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@AJenbo please see whether this works for you

@staabm
staabm marked this pull request as ready for review October 16, 2026 20:07
@phpstan-bot

Copy link
Copy Markdown
Collaborator

This pull request has been marked as ready for review.

@staabm

staabm commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@DuckThom please check the phpstan phar file from the github action artifacts to verify whether this fixes the segfaults you experienced in phpstan/phpstan#15407

This comment was marked as outdated.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@staabm
staabm requested a balanced review from Copilot October 16, 2026 21:10

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@staabm
staabm requested a review from VincentLanglet October 17, 2026 01:24
@staabm

staabm commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

//cc @SanderMuller

@SanderMuller SanderMuller left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I checked this locally with Homebrew PHP 8.5.8 and pcov 1.0.12, loaded from a scanned ini file. A bootstrap file logged the state of the main process and of its forked worker:

  • 2.3.x (e4f45f9) with pcov enabled: no restart, and pcov is loaded and enabled in both processes.
  • This PR with pcov enabled: one restart, and pcov is not loaded in either process.
  • This PR with pcov.enabled=0, or without pcov: no restart.
  • pcov loaded with -d extension= on the command line: where the Turbo restart runs, it already drops pcov, so this restart does not run.

Cold self-analysis with pcov enabled, 3 interleaved rounds: the median is 33.8 s on 2.3.x and 25.1 s with this PR. Every PR run was faster than every base run. A one-file run showed no difference: the median is 1.42 s on 2.3.x and 1.31 s with this PR. Single runs took 0.8 s to 2.0 s. Without pcov or tideways nothing restarts, so nothing changes there.

make tests, make phpstan and phpcs pass on the PR head. The 4 red jobs (both shopsys/shopsys jobs, PMMP and result-cache-parse-error) also fail on #6754 and #6756.

Copilot's comment was about the earlier regex. 47ccd22 also matches extension=, and I confirmed that it removes pcov. Its second point, an e2e check that the extension is gone, is still open.

Two suggestions. The first is that second Copilot point. "Process restarting" shows that a restart ran, not that pcov is gone. At 7c5bd7f the regex matched only zend_extension=, so pcov stayed loaded, and all three jobs still passed. A bootstrap file catches that:

<?php declare(strict_types = 1);

if (extension_loaded('pcov')) {
	fwrite(STDERR, "pcov is still loaded after the restart\n");
	exit(1);
}

With it, 7c5bd7f and 2.3.x exit with 1, and this PR exits with 0.

The second is small. In restart(), preg_replace() returns null on a PCRE error. Then null . PHP_EOL replaces the tmp ini with an empty line, and the restarted process runs without any php.ini settings. A null check before the write avoids that.

Two observations, neither of them blocking:

  • --xdebug and PHPSTAN_ALLOW_XDEBUG now also keep pcov and tideways loaded. That seems like the right escape hatch, but the option's description says only "Allow running with Xdebug for debugging purposes".
  • bin/phpstan runs the Turbo restart before this one. The tmp ini does not carry the phpstan.restarted marker and switches OPcache off again. So the restarted process runs the Turbo restart a second time. This already happens with Xdebug. Running this check first could save one exec. That is not a small change, because the Turbo restart runs before the autoloader. I did not try it.

I did not test tideways or Windows.

@AJenbo

AJenbo commented Oct 17, 2026

Copy link
Copy Markdown
Contributor

sorry I have been taking long with my version, I got it rebased on 2.3, but still need to go over it before it's ready

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.

Turbo 2.3.0 incompatible with Tideways

6 participants