Skip to content

Commit 9e6a5cd

Browse files
ondrejmirtesclaude
andcommitted
Print parallel worker mechanism via DiagnoseExtension
ForkParallelChecker now implements DiagnoseExtension (like Scheduler): under -vvv it prints whether parallel workers are spawned or forked, and — if PHPSTAN_PARALLEL_FORK=1 is set but the fork path still wasn't taken — it explains which precondition (pcntl/posix availability or OPcache/ JIT being off) is missing. The ad-hoc "Note: using pcntl_fork()…" lines that ParallelAnalyser and FixerApplication used to write to stderr in verbose mode are removed in favour of this. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0aaaa47 commit 9e6a5cd

3 files changed

Lines changed: 31 additions & 16 deletions

File tree

src/Command/FixerApplication.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ public function run(
113113
): int
114114
{
115115
$projectConfigFile = $inceptionResult->getProjectConfigFile();
116-
if ($this->forkParallelChecker->isSupported() && $output->isVerbose()) {
117-
$output->writeln('Note: using pcntl_fork() for the PHPStan Pro worker (experimental).');
118-
}
119116

120117
$loop = new StreamSelectLoop();
121118
$server = new TcpServer('127.0.0.1:0', $loop);

src/Parallel/ForkParallelChecker.php

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace PHPStan\Parallel;
44

5+
use PHPStan\Command\Output;
56
use PHPStan\DependencyInjection\AutowiredService;
7+
use PHPStan\Diagnose\DiagnoseExtension;
68
use function function_exists;
79
use function getenv;
810
use function opcache_get_status;
11+
use function sprintf;
912

1013
/**
1114
* Decides whether parallel analysis should fork workers via pcntl_fork()
@@ -17,10 +20,33 @@
1720
* doing so corrupts analysis results.
1821
*/
1922
#[AutowiredService]
20-
final class ForkParallelChecker
23+
final class ForkParallelChecker implements DiagnoseExtension
2124
{
2225

2326
public function isSupported(): bool
27+
{
28+
return $this->getDisabledReason() === null;
29+
}
30+
31+
public function print(Output $output): void
32+
{
33+
$output->writeLineFormatted('<info>Parallel worker creation:</info>');
34+
35+
$reason = $this->getDisabledReason();
36+
if ($reason === null) {
37+
$output->writeLineFormatted('Mechanism: fork (pcntl_fork — experimental)');
38+
$output->writeLineFormatted('');
39+
return;
40+
}
41+
42+
$output->writeLineFormatted('Mechanism: spawn (react/child-process)');
43+
if (getenv('PHPSTAN_PARALLEL_FORK') === '1') {
44+
$output->writeLineFormatted(sprintf('Reason fork not used: %s', $reason));
45+
}
46+
$output->writeLineFormatted('');
47+
}
48+
49+
private function getDisabledReason(): ?string
2450
{
2551
if (
2652
!function_exists('pcntl_fork')
@@ -29,21 +55,18 @@ public function isSupported(): bool
2955
|| !function_exists('pcntl_wexitstatus')
3056
|| !function_exists('posix_kill')
3157
) {
32-
return false;
58+
return 'pcntl/posix functions are not available';
3359
}
3460

3561
if (getenv('PHPSTAN_PARALLEL_FORK') !== '1') {
36-
return false;
62+
return 'PHPSTAN_PARALLEL_FORK environment variable is not set to "1"';
3763
}
3864

39-
// OPcache's shared memory and the JIT buffer are not safe to populate
40-
// concurrently from multiple forked children — doing so corrupts
41-
// analysis results. Forked workers require OPcache and JIT to be off.
4265
if ($this->isOpcacheOrJitEnabled()) {
43-
return false;
66+
return 'OPcache or JIT is enabled (forked workers require both to be off — their shared memory corrupts under concurrent population)';
4467
}
4568

46-
return true;
69+
return null;
4770
}
4871

4972
private function isOpcacheOrJitEnabled(): bool

src/Parallel/ParallelAnalyser.php

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,13 @@
2727
use function count;
2828
use function defined;
2929
use function escapeshellarg;
30-
use function fwrite;
3130
use function ini_get;
3231
use function max;
3332
use function memory_get_usage;
3433
use function parse_url;
3534
use function sprintf;
3635
use function str_contains;
3736
use const PHP_URL_PORT;
38-
use const STDERR;
3937

4038
#[AutowiredService]
4139
final class ParallelAnalyser
@@ -177,9 +175,6 @@ public function analyse(
177175
};
178176

179177
$useFork = $this->forkParallelChecker->isSupported();
180-
if ($useFork && $input->hasParameterOption(['-v', '-vv', '-vvv', '--verbose'], true)) {
181-
fwrite(STDERR, "Note: using pcntl_fork() for parallel workers (experimental).\n");
182-
}
183178

184179
for ($i = 0; $i < $numberOfProcesses; $i++) {
185180
if (count($jobs) === 0) {

0 commit comments

Comments
 (0)