From 5c066a5779b2ca213a7fae009b0b46de9aa78c2a Mon Sep 17 00:00:00 2001 From: coltbg Date: Wed, 18 Dec 2024 00:32:23 +0200 Subject: [PATCH] Fix: Prevent exception when parsing request port in ServeCommand ### Summary This PR fixes an issue where `php artisan serve` throws an exception on Windows when a log line does not contain a valid request port. ### Problem "process forking is not supported" when running the "artisan serve", and the `flushOutputBuffer` method tries to parse invalid lines. This raises the exception ### Solution - Added a guard condition to check if the line contains the expected keywords (`Accepted`, `Closing`) before calling `getRequestPortFromLine`. - Ensured no exception is thrown for invalid lines. ### Changes Made - Updated `flushOutputBuffer` method in `ServeCommand.php`: - Added `contains()` checks for specific keywords. - Skipped port parsing for invalid lines. ### How to Test 1. Run `php artisan serve`. 2. Verify that no exception occurs when invalid lines are logged. 3. Check that server output behaves as expected. --- .../Foundation/Console/ServeCommand.php | 61 ++++++++++--------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/Illuminate/Foundation/Console/ServeCommand.php b/src/Illuminate/Foundation/Console/ServeCommand.php index f64cbe300382..eaf30b82eb96 100644 --- a/src/Illuminate/Foundation/Console/ServeCommand.php +++ b/src/Illuminate/Foundation/Console/ServeCommand.php @@ -295,49 +295,50 @@ protected function flushOutputBuffer() return; } - $requestPort = static::getRequestPortFromLine($line); - - if ($stringable->contains(' Accepted')) { - $this->requestsPool[$requestPort] = [ - $this->getDateFromLine($line), - $this->requestsPool[$requestPort][1] ?? false, - microtime(true), - ]; - } elseif ($stringable->contains([' [200]: GET '])) { - $this->requestsPool[$requestPort][1] = trim(explode('[200]: GET', $line)[1]); - } elseif ($stringable->contains('URI:')) { - $this->requestsPool[$requestPort][1] = trim(explode('URI: ', $line)[1]); - } elseif ($stringable->contains(' Closing')) { - $requestPort = static::getRequestPortFromLine($line); - - if (empty($this->requestsPool[$requestPort])) { + if ($stringable->contains([' Accepted', ' Closing'])) { + // Only attempt to extract the request port if the line contains the necessary keywords. + $requestPort = null; + + if ($stringable->contains(' Accepted') || $stringable->contains(' Closing')) { + $requestPort = static::getRequestPortFromLine($line); + } + + if ($stringable->contains(' Accepted') && $requestPort !== null) { $this->requestsPool[$requestPort] = [ $this->getDateFromLine($line), - false, + $this->requestsPool[$requestPort][1] ?? false, microtime(true), ]; - } + } elseif ($stringable->contains([' Closing']) && $requestPort !== null) { + if (empty($this->requestsPool[$requestPort])) { + $this->requestsPool[$requestPort] = [ + $this->getDateFromLine($line), + false, + microtime(true), + ]; + } - [$startDate, $file, $startMicrotime] = $this->requestsPool[$requestPort]; + [$startDate, $file, $startMicrotime] = $this->requestsPool[$requestPort]; - $formattedStartedAt = $startDate->format('Y-m-d H:i:s'); + $formattedStartedAt = $startDate->format('Y-m-d H:i:s'); - unset($this->requestsPool[$requestPort]); + unset($this->requestsPool[$requestPort]); - [$date, $time] = explode(' ', $formattedStartedAt); + [$date, $time] = explode(' ', $formattedStartedAt); - $this->output->write(" $date $time"); + $this->output->write(" $date $time"); - $runTime = $this->runTimeForHumans($startMicrotime); + $runTime = $this->runTimeForHumans($startMicrotime); - if ($file) { - $this->output->write($file = " $file"); - } + if ($file) { + $this->output->write($file = " $file"); + } - $dots = max(terminal()->width() - mb_strlen($formattedStartedAt) - mb_strlen($file) - mb_strlen($runTime) - 9, 0); + $dots = max(terminal()->width() - mb_strlen($formattedStartedAt) - mb_strlen($file) - mb_strlen($runTime) - 9, 0); - $this->output->write(' '.str_repeat('.', $dots)); - $this->output->writeln(" ~ {$runTime}"); + $this->output->write(' '.str_repeat('.', $dots)); + $this->output->writeln(" ~ {$runTime}"); + } } elseif ($stringable->contains(['Closed without sending a request', 'Failed to poll event'])) { // ... } elseif (! empty($line)) {