Skip to content

Commit 7631cbc

Browse files
committed
Implement proper error checking around pcntl_waitpid calls
Related to #22563 and #21852
1 parent 49b3c72 commit 7631cbc

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

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

Lines changed: 36 additions & 11 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))
@@ -339,13 +336,29 @@ private function isDeployed(Package $package)
339336
if ($this->isCanBeParalleled()) {
340337
if ($package->getState() === null) {
341338
// phpcs:ignore Magento2.Functions.DiscouragedFunction
342-
$pid = pcntl_waitpid($this->getPid($package), $status, WNOHANG);
343-
if ($pid === $this->getPid($package)) {
339+
$result = pcntl_waitpid($pid, $status, WNOHANG);
340+
if ($result === $pid) {
344341
$package->setState(Package::STATE_COMPLETED);
342+
$exitStatus = pcntl_wexitstatus($status);
343+
344+
$this->logger->info(
345+
"Exited: " . $package->getPath() . "(status: $exitStatus)",
346+
[
347+
'process' => $package->getPath(),
348+
'status' => $exitStatus,
349+
]
350+
);
345351

346352
unset($this->inProgress[$package->getPath()]);
347353
// phpcs:ignore Magento2.Functions.DiscouragedFunction
348354
return pcntl_wexitstatus($status) === 0;
355+
} elseif ($result === -1) {
356+
$errno = pcntl_errno();
357+
$strerror = pcntl_strerror($errno);
358+
359+
throw new \RuntimeException(
360+
"Error encountered checking child process status (PID: $pid): $strerror (errno: $errno)"
361+
);
349362
}
350363
return false;
351364
}
@@ -385,10 +398,22 @@ private function checkTimeout()
385398
public function __destruct()
386399
{
387400
foreach ($this->inProgress as $package) {
401+
$pid = $this->getPid($package);
402+
$this->logger->info(
403+
"Reaping child process: {$package->getPath()} (PID: $pid)",
404+
[
405+
'process' => $package->getPath(),
406+
'pid' => $pid,
407+
]
408+
);
409+
388410
// phpcs:ignore Magento2.Functions.DiscouragedFunction
389-
if (pcntl_waitpid($this->getPid($package), $status) === -1) {
411+
if (pcntl_waitpid($pid, $status) === -1) {
412+
$errno = pcntl_errno();
413+
$strerror = pcntl_strerror($errno);
414+
390415
throw new \RuntimeException(
391-
'Error while waiting for package deployed: ' . $this->getPid($package) . '; Status: ' . $status
416+
"Error encountered waiting for child process (PID: $pid): $strerror (errno: $errno)"
392417
);
393418
}
394419
}

0 commit comments

Comments
 (0)