Skip to content

Commit 246b88c

Browse files
ENGCOM-5098: Implement Better Error Handling and Fix Waits on Null PIDs in Parallel SCD Execution #22607
- Merge Pull Request #22607 from davidalger/magento2:pcntl-scd-fix-23 - Merged commits: 1. 49b3c72 2. 7631cbc 3. e1525a8 4. 8d0a3d8
2 parents 72aebb7 + 8d0a3d8 commit 246b88c

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

app/code/Magento/Deploy/Process/Queue.php

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
use Magento\Deploy\Package\Package;
1111
use Magento\Deploy\Service\DeployPackage;
1212
use Magento\Framework\App\ResourceConnection;
13-
use Psr\Log\LoggerInterface;
1413
use Magento\Framework\App\State as AppState;
1514
use Magento\Framework\Locale\ResolverInterface as LocaleResolver;
15+
use Psr\Log\LoggerInterface;
1616

1717
/**
1818
* Deployment Queue
@@ -165,6 +165,7 @@ public function process()
165165
$packages = $this->packages;
166166
while (count($packages) && $this->checkTimeout()) {
167167
foreach ($packages as $name => $packageJob) {
168+
// Unsets each member of $packages array (passed by reference) as each is executed
168169
$this->assertAndExecute($name, $packages, $packageJob);
169170
}
170171
$this->logger->info('.');
@@ -224,12 +225,8 @@ private function assertAndExecute($name, array & $packages, array $packageJob)
224225
* @param bool $dependenciesNotFinished
225226
* @return void
226227
*/
227-
private function executePackage(
228-
Package $package,
229-
string $name,
230-
array &$packages,
231-
bool $dependenciesNotFinished
232-
) {
228+
private function executePackage(Package $package, string $name, array &$packages, bool $dependenciesNotFinished)
229+
{
233230
if (!$dependenciesNotFinished
234231
&& !$this->isDeployed($package)
235232
&& ($this->maxProcesses < 2 || (count($this->inProgress) < $this->maxProcesses))
@@ -338,14 +335,38 @@ private function isDeployed(Package $package)
338335
{
339336
if ($this->isCanBeParalleled()) {
340337
if ($package->getState() === null) {
338+
$pid = $this->getPid($package);
339+
340+
// When $pid comes back as null the child process for this package has not yet started; prevents both
341+
// hanging until timeout expires (which was behaviour in 2.2.x) and the type error from strict_types
342+
if ($pid === null) {
343+
return false;
344+
}
345+
341346
// phpcs:ignore Magento2.Functions.DiscouragedFunction
342-
$pid = pcntl_waitpid($this->getPid($package), $status, WNOHANG);
343-
if ($pid === $this->getPid($package)) {
347+
$result = pcntl_waitpid($pid, $status, WNOHANG);
348+
if ($result === $pid) {
344349
$package->setState(Package::STATE_COMPLETED);
350+
$exitStatus = pcntl_wexitstatus($status);
351+
352+
$this->logger->info(
353+
"Exited: " . $package->getPath() . "(status: $exitStatus)",
354+
[
355+
'process' => $package->getPath(),
356+
'status' => $exitStatus,
357+
]
358+
);
345359

346360
unset($this->inProgress[$package->getPath()]);
347361
// phpcs:ignore Magento2.Functions.DiscouragedFunction
348362
return pcntl_wexitstatus($status) === 0;
363+
} elseif ($result === -1) {
364+
$errno = pcntl_errno();
365+
$strerror = pcntl_strerror($errno);
366+
367+
throw new \RuntimeException(
368+
"Error encountered checking child process status (PID: $pid): $strerror (errno: $errno)"
369+
);
349370
}
350371
return false;
351372
}
@@ -361,7 +382,7 @@ private function isDeployed(Package $package)
361382
*/
362383
private function getPid(Package $package)
363384
{
364-
return isset($this->processIds[$package->getPath()]) ?? null;
385+
return $this->processIds[$package->getPath()] ?? null;
365386
}
366387

367388
/**
@@ -385,10 +406,22 @@ private function checkTimeout()
385406
public function __destruct()
386407
{
387408
foreach ($this->inProgress as $package) {
409+
$pid = $this->getPid($package);
410+
$this->logger->info(
411+
"Reaping child process: {$package->getPath()} (PID: $pid)",
412+
[
413+
'process' => $package->getPath(),
414+
'pid' => $pid,
415+
]
416+
);
417+
388418
// phpcs:ignore Magento2.Functions.DiscouragedFunction
389-
if (pcntl_waitpid($this->getPid($package), $status) === -1) {
419+
if (pcntl_waitpid($pid, $status) === -1) {
420+
$errno = pcntl_errno();
421+
$strerror = pcntl_strerror($errno);
422+
390423
throw new \RuntimeException(
391-
'Error while waiting for package deployed: ' . $this->getPid($package) . '; Status: ' . $status
424+
"Error encountered waiting for child process (PID: $pid): $strerror (errno: $errno)"
392425
);
393426
}
394427
}

0 commit comments

Comments
 (0)