fix: add waitpid safety net for distro init signalfd setup (#40229)
When setting up signalfd to watch distroInitPid, there is a window where the child can exit before the signal infrastructure is ready: either auto-reaped under SIG_IGN before we reach this code, or exiting between signal(SIG_DFL) and sigprocmask(SIG_BLOCK) where the SIGCHLD is discarded. Add a non-blocking waitpid check after signalfd setup to catch both cases, preventing an unrecoverable hang if the distro init exits during startup. Also fixes the existing loop to check waitpid return (Pid) instead of poll return (Result) when handling SIGCHLD. Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Ben Hillis committed
Apr 20, 2026 at 15:26 UTC
8e5b4a9aa6d0ffb79de53d9375e671093e5837be
1 file changed
+10
src/linux/init/init.cpp
+10
@@ -2426,6 +2426,16 @@ Return Value:
2426
FATAL_ERROR("signalfd failed {}", errno);
2427
}
2428
2429
+ // Handle the case where the child already exited before signalfd was set up.
2430
+ int Status{};
2431
+ auto WaitResult = waitpid(distroInitPid.value(), &Status, WNOHANG);
2432
+ if (WaitResult > 0 || (WaitResult < 0 && errno == ECHILD))
2433
+ {
2434
+ LOG_ERROR("Init has exited. Terminating distribution");
2435
+ InitTerminateInstanceInternal(Config);
2436
+ return;
2437
+ }
2438
+
2439
PollDescriptors.resize(2);
2440
PollDescriptors[1].fd = SignalFd.get();
2441
PollDescriptors[1].events = POLLIN;