diff --git a/src/Illuminate/Concurrency/ProcessDriver.php b/src/Illuminate/Concurrency/ProcessDriver.php index 775245212cc0..9d82e75bc96b 100644 --- a/src/Illuminate/Concurrency/ProcessDriver.php +++ b/src/Illuminate/Concurrency/ProcessDriver.php @@ -8,6 +8,7 @@ use Illuminate\Process\Factory as ProcessFactory; use Illuminate\Process\Pool; use Illuminate\Support\Arr; +use Illuminate\Support\ProcessUtils; use Laravel\SerializableClosure\SerializableClosure; use Symfony\Component\Process\PhpExecutableFinder; @@ -26,18 +27,13 @@ public function __construct(protected ProcessFactory $processFactory) */ public function run(Closure|array $tasks): array { - $php = $this->phpBinary(); - $artisan = $this->artisanBinary(); + $command = $this->buildCommand(); - $results = $this->processFactory->pool(function (Pool $pool) use ($tasks, $php, $artisan) { + $results = $this->processFactory->pool(function (Pool $pool) use ($tasks, $command) { foreach (Arr::wrap($tasks) as $task) { $pool->path(base_path())->env([ 'LARAVEL_INVOKABLE_CLOSURE' => serialize(new SerializableClosure($task)), - ])->command([ - $php, - $artisan, - 'invoke-serialized-closure', - ]); + ])->command($command); } })->start()->wait(); @@ -59,7 +55,15 @@ public function run(Closure|array $tasks): array */ public function defer(Closure|array $tasks): DeferredCallback { - return defer(fn () => $this->run($tasks)); + $command = $this->buildCommand(); + + return defer(function () use ($tasks, $command) { + foreach (Arr::wrap($tasks) as $task) { + $this->processFactory->path(base_path())->env([ + 'LARAVEL_INVOKABLE_CLOSURE' => serialize(new SerializableClosure($task)), + ])->run($command.' 2>&1 &'); + } + }); } /** @@ -67,7 +71,7 @@ public function defer(Closure|array $tasks): DeferredCallback */ protected function phpBinary(): string { - return (new PhpExecutableFinder)->find(false) ?: 'php'; + return ProcessUtils::escapeArgument((new PhpExecutableFinder)->find(false) ?: 'php'); } /** @@ -75,6 +79,16 @@ protected function phpBinary(): string */ protected function artisanBinary(): string { - return defined('ARTISAN_BINARY') ? ARTISAN_BINARY : 'artisan'; + return ProcessUtils::escapeArgument(defined('ARTISAN_BINARY') ? ARTISAN_BINARY : 'artisan'); + } + + /** + * Build the command string. + * + * @return string + */ + protected function buildCommand(): string + { + return sprintf('%s %s invoke-serialized-closure', $this->phpBinary(), $this->artisanBinary()); } }