1010use Magento \Deploy \Package \Package ;
1111use Magento \Deploy \Service \DeployPackage ;
1212use Magento \Framework \App \ResourceConnection ;
13- use Psr \Log \LoggerInterface ;
1413use Magento \Framework \App \State as AppState ;
1514use 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,41 @@ 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+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
351+ $ exitStatus = pcntl_wexitstatus ($ status );
352+
353+ $ this ->logger ->info (
354+ "Exited: " . $ package ->getPath () . "(status: $ exitStatus) " ,
355+ [
356+ 'process ' => $ package ->getPath (),
357+ 'status ' => $ exitStatus ,
358+ ]
359+ );
345360
346361 unset($ this ->inProgress [$ package ->getPath ()]);
347362 // phpcs:ignore Magento2.Functions.DiscouragedFunction
348363 return pcntl_wexitstatus ($ status ) === 0 ;
364+ } elseif ($ result === -1 ) {
365+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
366+ $ errno = pcntl_errno ();
367+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
368+ $ strerror = pcntl_strerror ($ errno );
369+
370+ throw new \RuntimeException (
371+ "Error encountered checking child process status (PID: $ pid): $ strerror (errno: $ errno) "
372+ );
349373 }
350374 return false ;
351375 }
@@ -361,7 +385,7 @@ private function isDeployed(Package $package)
361385 */
362386 private function getPid (Package $ package )
363387 {
364- return isset ( $ this ->processIds [$ package ->getPath ()]) ?? null ;
388+ return $ this ->processIds [$ package ->getPath ()] ?? null ;
365389 }
366390
367391 /**
@@ -380,15 +404,30 @@ private function checkTimeout()
380404 * Protect against zombie process
381405 *
382406 * @throws \RuntimeException
407+ * @SuppressWarnings(PHPMD.UnusedLocalVariable)
383408 * @return void
384409 */
385410 public function __destruct ()
386411 {
387412 foreach ($ this ->inProgress as $ package ) {
413+ $ pid = $ this ->getPid ($ package );
414+ $ this ->logger ->info (
415+ "Reaping child process: {$ package ->getPath ()} (PID: $ pid) " ,
416+ [
417+ 'process ' => $ package ->getPath (),
418+ 'pid ' => $ pid ,
419+ ]
420+ );
421+
388422 // phpcs:ignore Magento2.Functions.DiscouragedFunction
389- if (pcntl_waitpid ($ this ->getPid ($ package ), $ status ) === -1 ) {
423+ if (pcntl_waitpid ($ pid , $ status ) === -1 ) {
424+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
425+ $ errno = pcntl_errno ();
426+ // phpcs:ignore Magento2.Functions.DiscouragedFunction
427+ $ strerror = pcntl_strerror ($ errno );
428+
390429 throw new \RuntimeException (
391- ' Error while waiting for package deployed: ' . $ this -> getPid ( $ package ) . ' ; Status: ' . $ status
430+ " Error encountered waiting for child process (PID: $ pid ): $ strerror (errno: $ errno ) "
392431 );
393432 }
394433 }
0 commit comments