diff -Naur a/vendor/magento/module-deploy/Process/Queue.php b/vendor/magento/module-deploy/Process/Queue.php
--- a/vendor/magento/module-deploy/Process/Queue.php
+++ b/vendor/magento/module-deploy/Process/Queue.php
@@ -338,14 +338,37 @@ class Queue
     {
         if ($this->isCanBeParalleled()) {
             if ($package->getState() === null) {
+                $pid = $this->getPid($package);
+                // When $pid comes back as null the child process for this package has not yet started; prevents both
+                // hanging until timeout expires (which was behaviour in 2.2.x) and the type error from strict_types
+                if ($pid === null) {
+                    return false;
+                }
                 // phpcs:ignore Magento2.Functions.DiscouragedFunction
-                $pid = pcntl_waitpid($this->getPid($package) ?? 0, $status, WNOHANG);
-                if ($pid === $this->getPid($package)) {
+                $result = pcntl_waitpid($pid, $status, WNOHANG);
+                if ($result === $pid) {
                     $package->setState(Package::STATE_COMPLETED);
+                    // phpcs:ignore Magento2.Functions.DiscouragedFunction
+                    $exitStatus = pcntl_wexitstatus($status);
+                    $this->logger->info(
+                        "Exited: " . $package->getPath() . "(status: $exitStatus)",
+                        [
+                            'process' => $package->getPath(),
+                            'status' => $exitStatus,
+                        ]
+                    );

                     unset($this->inProgress[$package->getPath()]);
                     // phpcs:ignore Magento2.Functions.DiscouragedFunction
                     return pcntl_wexitstatus($status) === 0;
+                } elseif ($result === -1) {
+                    // phpcs:ignore Magento2.Functions.DiscouragedFunction
+                    $errno = pcntl_errno();
+                    // phpcs:ignore Magento2.Functions.DiscouragedFunction
+                    $strerror = pcntl_strerror($errno);
+                    throw new \RuntimeException(
+                        "Error encountered checking child process status (PID: $pid): $strerror (errno: $errno)"
+                    );
                 }
                 return false;
             }
@@ -385,10 +408,24 @@ class Queue
     public function __destruct()
     {
         foreach ($this->inProgress as $package) {
+            $pid = $this->getPid($package);
+            $this->logger->info(
+                "Reaping child process: {$package->getPath()} (PID: $pid)",
+                [
+                    'process' => $package->getPath(),
+                    'pid' => $pid,
+                ]
+            );
+
             // phpcs:ignore Magento2.Functions.DiscouragedFunction
-            if (pcntl_waitpid($this->getPid($package), $status) === -1) {
+            if (pcntl_waitpid($pid, $status) === -1) {
+                // phpcs:ignore Magento2.Functions.DiscouragedFunction
+                $errno = pcntl_errno();
+                // phpcs:ignore Magento2.Functions.DiscouragedFunction
+                $strerror = pcntl_strerror($errno);
+
                 throw new \RuntimeException(
-                    'Error while waiting for package deployed: ' . $this->getPid($package) . '; Status: ' . $status
+                    "Error encountered waiting for child process (PID: $pid): $strerror (errno: $errno)"
                 );
             }
         }
