From eaedb542e11a4662b1ec45bdfdfa32ec3c4e6e7a Mon Sep 17 00:00:00 2001 From: Daniel Hilst <392820+dhilst@users.noreply.github.com> Date: Thu, 27 Aug 2026 15:51:41 -0300 Subject: [PATCH] fix(xcat-core): a respawned install monitor is not the same process as the original The respawn forks from the main service loop, much further down the program than the fork at startup, so it inherits everything the parent has opened in between. That is the rescanplugins socketpair from further up this file -- the channel a subcommand process uses to hand a reloaded cmd_handlers hash back to the parent. The child closes the SSL listener and the UDP control socket but not those two, so a respawned monitor holds both ends of a channel it never reads or writes, for as long as it lives. Measured on a live MN by diffing /proc//fd between a monitor forked at startup and one respawned after being killed: the respawned process carried one extra socket, and both ends of that pair were also held by the SSL listener parent. The leak is two descriptors and it does not accumulate, since each respawn forks afresh from the parent; the reason to fix it is that the block is commented "serve only the install monitor" and no longer did, so a monitor's file descriptors depended on whether it was the first one or a replacement. That is the kind of difference that makes a later problem reproduce only on one path. Close both ends in the respawn child. The monitor's own plugin-rescan channel is a different socketpair, created before either fork, and is untouched. Verified afterwards on the same MN: the respawned monitor no longer shares a socketpair with the parent, and still binds xcatiport and serves it, with the SSL listener holding its pid throughout. Not covered by a test. Both the unit suite and the xCAT-test case format work at the level of processes and ports; this is an invariant about file descriptors that needs /proc on a running daemon, and asserting it there would be more fragile than the line it guards. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com> --- xCAT-server/sbin/xcatd | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xCAT-server/sbin/xcatd b/xCAT-server/sbin/xcatd index 5fa81df9a..b47b0ba8d 100755 --- a/xCAT-server/sbin/xcatd +++ b/xCAT-server/sbin/xcatd @@ -1516,6 +1516,12 @@ until ($quit) { $pid_UDP = 0; close($listener); close($udpctl); $udpctl = 0; + # This fork happens further down the program than the one at startup, so it also + # inherits what the parent has opened since: the rescanplugins channel. The monitor + # has no use for either end, and holding them is the only way a respawned monitor + # would differ from the one forked at startup. + close($chreadpipe); + close($chwritepipe); do_installm_service; xexit(0); } else {