If the worker finishes right after we `waitpid` but before we add it to `WORKER_PIDS` the `worker_reaper` won't `waitpid` it cause it iterates over `WORKER_PIDS`. So - the clean-up triggered by the SIGCHLD won't catch it cause it needs it to be in `WORKER_PIDS` - and, `register_worker` won't because it was still running when it `waitpid`'ed it
Moving the insertion into `WORKER_PIDS` before the `waitpid` solves this by making sure it is - always in the var for `worker_reaper` - and, if SIGCHILD should trigger `worker_reaper` before we add it to `WORKER_PIDS`, the `waitpid` in `register_worker` itself will catch it Signed-off-by: Hannes Laimer <[email protected]> --- src/PVE/RESTEnvironment.pm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/PVE/RESTEnvironment.pm b/src/PVE/RESTEnvironment.pm index 4ed5c05..4677687 100644 --- a/src/PVE/RESTEnvironment.pm +++ b/src/PVE/RESTEnvironment.pm @@ -99,17 +99,18 @@ my $register_worker = sub { return if !$pid; - # do not register if already finished + $WORKER_PIDS->{$pid} = { + user => $user, + upid => $upid, + }; + + # remove immediately if already finished my $waitpid = waitpid($pid, WNOHANG); if (defined($waitpid) && ($waitpid == $pid)) { delete($WORKER_PIDS->{$pid}); return; } - $WORKER_PIDS->{$pid} = { - user => $user, - upid => $upid, - }; }; # initialize environment - must be called once at program startup -- 2.47.3
