From 3763ff0219a75a4ab1db710ac0d5e2fcca7f534b Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Mon, 10 Mar 2025 21:53:59 -0300 Subject: [PATCH 1/4] Undo the multi-proc fix --- .../Foundation/Console/ServeCommand.php | 27 +++---------------- 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index 6b86bb65fa7a..bddc3172f1c1 100644 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -36,13 +36,6 @@ class ServeCommand extends Command */ protected $description = 'Serve the application on the PHP development server'; - /** - * The number of PHP CLI server workers. - * - * @var int<2, max>|false - */ - protected $phpServerWorkers = 1; - /** * The current port offset. * @@ -85,6 +78,7 @@ class ServeCommand extends Command 'IGNITION_LOCAL_SITES_PATH', 'LARAVEL_SAIL', 'PATH', + 'PHP_CLI_SERVER_WORKERS', 'PHP_IDE_CONFIG', 'SYSTEMROOT', 'XDEBUG_CONFIG', @@ -92,21 +86,6 @@ class ServeCommand extends Command 'XDEBUG_SESSION', ]; - /** {@inheritdoc} */ - #[\Override] - protected function initialize(InputInterface $input, OutputInterface $output) - { - $this->phpServerWorkers = transform((int) env('PHP_CLI_SERVER_WORKERS', 1), function (int $workers) { - if ($workers < 2) { - return false; - } - - return $workers > 1 && ! $this->option('no-reload') ? false : $workers; - }); - - parent::initialize($input, $output); - } - /** * Execute the console command. * @@ -177,7 +156,7 @@ protected function startProcess($hasEnvironment) } return in_array($key, static::$passthroughVariables) ? [$key => $value] : [$key => false]; - })->merge(['PHP_CLI_SERVER_WORKERS' => $this->phpServerWorkers])->all()); + })->all()); $this->trap(fn () => [SIGTERM, SIGINT, SIGHUP, SIGUSR1, SIGUSR2, SIGQUIT], function ($signal) use ($process) { if ($process->isRunning()) { @@ -383,7 +362,7 @@ protected function flushOutputBuffer() */ protected function getDateFromLine($line) { - $regex = ! windows_os() && is_int($this->phpServerWorkers) + $regex = ! windows_os() && env('PHP_CLI_SERVER_WORKERS', 1) > 1 ? '/^\[\d+]\s\[([a-zA-Z0-9: ]+)\]/' : '/^\[([^\]]+)\]/'; From e0c8bdc0d769a2aa46e7ceff4529c5627c32f45a Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Mon, 10 Mar 2025 22:17:47 -0300 Subject: [PATCH 2/4] Disable auto-reload of env changes when there are multiple processes --- .../Foundation/Console/ServeCommand.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index bddc3172f1c1..fe3061a6ccf1 100644 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -112,7 +112,7 @@ public function handle() clearstatcache(false, $environmentFile); } - if (! $this->option('no-reload') && + if ($this->shouldAutoReload() && $hasEnvironment && filemtime($environmentFile) > $environmentLastModified) { $environmentLastModified = filemtime($environmentFile); @@ -151,7 +151,7 @@ public function handle() protected function startProcess($hasEnvironment) { $process = new Process($this->serverCommand(), public_path(), (new Collection($_ENV))->mapWithKeys(function ($value, $key) use ($hasEnvironment) { - if ($this->option('no-reload') || ! $hasEnvironment) { + if (! $this->shouldAutoReload() || ! $hasEnvironment) { return [$key => $value]; } @@ -211,6 +211,7 @@ protected function port() { $port = $this->input->getOption('port'); + if (is_null($port)) { [, $port] = $this->getHostAndPort(); } @@ -404,4 +405,16 @@ protected function getOptions() ['no-reload', null, InputOption::VALUE_NONE, 'Do not reload the development server on .env file changes'], ]; } + + /** + * Determines if the processes should autoreload. + */ + protected function shouldAutoReload(): bool + { + if (env('PHP_CLI_SERVER_WORKERS', 1) > 1) { + return false; + } + + return ! $this->option('no-reload'); + } } From 6c3520b0ecccf22e9ecb2cca14f7f680261c5fdd Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Mon, 10 Mar 2025 23:24:04 -0300 Subject: [PATCH 3/4] StyleCI --- src/Illuminate/Foundation/Console/ServeCommand.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index fe3061a6ccf1..d1af25fc35b1 100644 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -9,9 +9,7 @@ use Illuminate\Support\InteractsWithTime; use Illuminate\Support\Stringable; use Symfony\Component\Console\Attribute\AsCommand; -use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Process; use function Illuminate\Support\php_binary; @@ -211,7 +209,6 @@ protected function port() { $port = $this->input->getOption('port'); - if (is_null($port)) { [, $port] = $this->getHostAndPort(); } From 63b03c4ba429570d8a5d21f562ac7447f9c2ec96 Mon Sep 17 00:00:00 2001 From: Tony Messias Date: Tue, 11 Mar 2025 09:55:02 -0300 Subject: [PATCH 4/4] Wait until port is available --- .../Foundation/Console/ServeCommand.php | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index d1af25fc35b1..1c1a48c44717 100644 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -8,6 +8,7 @@ use Illuminate\Support\Env; use Illuminate\Support\InteractsWithTime; use Illuminate\Support\Stringable; +use RuntimeException; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Process\Process; @@ -123,6 +124,8 @@ public function handle() $this->serverRunningHasBeenDisplayed = false; + $this->waitUntilPortIsAvailableOrFail($this->host(), $this->port()); + $process = $this->startProcess($hasEnvironment); } @@ -408,10 +411,31 @@ protected function getOptions() */ protected function shouldAutoReload(): bool { - if (env('PHP_CLI_SERVER_WORKERS', 1) > 1) { - return false; + return ! $this->option('no-reload'); + } + + /** + * Waits for the ports to become available and throws an exception if it never does. + */ + protected function waitUntilPortIsAvailableOrFail(string $host, string $port): void + { + for ($i = 1; $i <= 3; $i++) { + // To check if the port is available, we'll attempt to open a socket connection to it. + // Note that the logic here is flipped: successfully opening the socket connection + // means something is using it. If it fails to open, that port is likely unused. + + $socket = @fsockopen($host, $port, $errorCode, $errorMessage, timeout: 5); + + if (! $socket) { + return; + } + + fclose($socket); + + // Gradually increase the waiting time between attempts... + usleep(1_000_000 * $i); } - return ! $this->option('no-reload'); + throw new RuntimeException("Port {$port} was not released."); } }