Skip to content

Commit 0b9a9d1

Browse files
authored
Restart process when pcov or tideways extension is loaded (#6757)
1 parent 807d030 commit 0b9a9d1

3 files changed

Lines changed: 80 additions & 6 deletions

File tree

‎.github/workflows/e2e-tests.yml‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2028,6 +2028,23 @@ jobs:
20282028
../bashunit -a contains 'Foo.php:11:Instantiated class Ds\Vector not found.' "$OUTPUT"
20292029
../bashunit -a contains 'Bar.php:15:Call to an undefined method Ds\Pair<string, int>::copy().' "$OUTPUT"
20302030
../bashunit -a not_contains 'Ds\Seq' "$OUTPUT"
2031+
- script: |
2032+
echo "<?php echo 'Hello 1';" > test.php
2033+
XDEBUG_HANDLER_DEBUG=1 bin/phpstan analyse test.php 2>&1 | tee -a output.txt
2034+
e2e/bashunit -a file_contains output.txt "Process restarting"
2035+
coverage: "pcov"
2036+
- script: |
2037+
echo "<?php echo 'Hello 2';" > test.php
2038+
XDEBUG_HANDLER_DEBUG=1 bin/phpstan analyse test.php 2>&1 | tee -a output.txt
2039+
e2e/bashunit -a file_contains output.txt "Process restarting"
2040+
coverage: "pcov"
2041+
ini-values: "pcov.enabled=1"
2042+
- script: |
2043+
echo "<?php echo 'Hello 3';" > test.php
2044+
XDEBUG_HANDLER_DEBUG=1 bin/phpstan analyse test.php 2>&1 | tee -a output.txt
2045+
e2e/bashunit -a file_not_contains output.txt "Process restarting"
2046+
coverage: "pcov"
2047+
ini-values: "pcov.enabled=0"
20312048
20322049
steps:
20332050
- name: Harden the runner (Audit all outbound calls)
@@ -2041,7 +2058,8 @@ jobs:
20412058
- name: "Install PHP"
20422059
uses: "shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962" # 2.40.0
20432060
with:
2044-
coverage: "none"
2061+
coverage: ${{ matrix.coverage || 'none' }}
2062+
ini-values: ${{ matrix.ini-values || '' }}
20452063
php-version: "8.2"
20462064
tools: ${{ matrix.tools }}
20472065
extensions: ${{ matrix.extensions }}

‎src/Command/CommandHelper.php‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace PHPStan\Command;
44

55
use Composer\Semver\Semver;
6-
use Composer\XdebugHandler\XdebugHandler;
76
use Nette\DI\Helpers;
87
use Nette\DI\InvalidConfigurationException;
98
use Nette\DI\ServiceCreationException;
@@ -32,6 +31,7 @@
3231
use PHPStan\Internal\DirectoryCreator;
3332
use PHPStan\Internal\DirectoryCreatorException;
3433
use PHPStan\Process\ForkedChildCrashReporter;
34+
use PHPStan\Process\ProcessRestarter;
3535
use PHPStan\ShouldNotHappenException;
3636
use ReflectionClass;
3737
use Symfony\Component\Console\Input\InputInterface;
@@ -104,22 +104,22 @@ public static function begin(
104104
$errorOutput = new SymfonyOutput($symfonyErrorOutput, new SymfonyStyle(new ErrorsConsoleStyle($input, $symfonyErrorOutput)));
105105

106106
if (!$allowXdebug) {
107-
$xdebug = new XdebugHandler('phpstan');
107+
$xdebug = new ProcessRestarter('phpstan');
108108
$xdebug->setPersistent();
109109
$xdebug->check();
110110
unset($xdebug);
111111
}
112112

113113
if ($allowXdebug) {
114-
if (!XdebugHandler::isXdebugActive()) {
114+
if (!ProcessRestarter::isXdebugActive()) {
115115
$errorOutput->getStyle()->note('You are running with "--xdebug" enabled, but the Xdebug PHP extension is not active. The process will not halt at breakpoints.');
116116
} else {
117117
$errorOutput->getStyle()->note("You are running with \"--xdebug\" enabled, and the Xdebug PHP extension is active.\nThe process will halt at breakpoints, but PHPStan will run much slower.\nUse this only if you are debugging PHPStan itself or your custom extensions.");
118118
}
119-
} elseif (XdebugHandler::isXdebugActive()) {
119+
} elseif (ProcessRestarter::isXdebugActive()) {
120120
$errorOutput->getStyle()->note('The Xdebug PHP extension is active, but "--xdebug" is not used. This may slow down performance and the process will not halt at breakpoints.');
121121
} elseif ($debugEnabled) {
122-
$v = XdebugHandler::getSkippedVersion();
122+
$v = ProcessRestarter::getSkippedVersion();
123123
if ($v !== '') {
124124
$errorOutput->getStyle()->note(
125125
"The Xdebug PHP extension is active, but \"--xdebug\" is not used.\n" .

‎src/Process/ProcessRestarter.php‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Process;
4+
5+
use Composer\XdebugHandler\XdebugHandler;
6+
use Override;
7+
use function count;
8+
use function extension_loaded;
9+
use function file_get_contents;
10+
use function file_put_contents;
11+
use function ini_get;
12+
use function preg_replace;
13+
use const PHP_EOL;
14+
15+
// see https://github.com/composer/xdebug-handler/issues/174
16+
final class ProcessRestarter extends XdebugHandler
17+
{
18+
19+
/** @var array<string> */
20+
private array $extensions = [];
21+
22+
#[Override]
23+
protected function requiresRestart(bool $default): bool
24+
{
25+
// pcov has a perf impact similar to xdebug, so we want to disable it
26+
if (extension_loaded('pcov') && ini_get('pcov.enabled') === '1') {
27+
$this->extensions[] = 'pcov';
28+
}
29+
30+
// tideways hooks deep in the php engine, so it can segfault when running phpstan with turbo.
31+
if (extension_loaded('tideways')) {
32+
$this->extensions[] = 'tideways';
33+
}
34+
35+
return $default || count($this->extensions) > 0;
36+
}
37+
38+
#[Override]
39+
protected function restart(array $command): void
40+
{
41+
if (count($this->extensions) > 0) {
42+
$content = file_get_contents((string) $this->tmpIni);
43+
44+
if ($content !== false) {
45+
foreach ($this->extensions as $extension) {
46+
$regex = '/^\s*((?:zend_)?extension\s*=.*' . $extension . '.*)$/mi';
47+
$content = preg_replace($regex, ';$1', $content) . PHP_EOL;
48+
}
49+
file_put_contents((string) $this->tmpIni, $content);
50+
}
51+
}
52+
53+
parent::restart($command);
54+
}
55+
56+
}

0 commit comments

Comments
 (0)