From 08ef174d64646ed2d78460a8021947e1208052df Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Wed, 25 Feb 2026 22:31:53 +0000 Subject: [PATCH] Fix signal handling - waiting for multiple processes In tooldata_db.cc (line 67), the old code does: 1. waitpid(..., WNOHANG) in a while (...) ; loop with an empty body. 2. Then evaluates WIFSIGNALED(status) and WIFEXITED(status) once, after the loop. The problem is: 1. waitpid only writes status when it returns > 0. 2. With WNOHANG, it can return 0 immediately (no state change yet), or -1 on error. 3. In those cases, status is not guaranteed to be written. 4. The code then reads status anyway via WIF* macros, so it can read stale/uninitialized data. 5. That can cause false logs and incorrectly set db_live = 0. What the patch changes: 1. It moves WIFSIGNALED/WIFEXITED checks inside the while (waitpid(...) > 0) loop. 2. status is only inspected in iterations where waitpid definitely produced a valid child status. 3. If no child was reapable, the loop does not run, and nothing is logged or toggled. 4. If multiple children changed state, each valid status is handled, instead of only the last one. --- src/emc/tooldata/tooldata_db.cc | 38 +++++++++++++++++---------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/emc/tooldata/tooldata_db.cc b/src/emc/tooldata/tooldata_db.cc index 25edbec18f4..33972bbd9ec 100644 --- a/src/emc/tooldata/tooldata_db.cc +++ b/src/emc/tooldata/tooldata_db.cc @@ -64,29 +64,31 @@ static int pipes[NUM_PIPES][2]; static bool is_random_toolchanger = 0; static char db_childname[PATH_MAX]; -static void handle_sigchild(int s) +static void handle_sigchild(int /*s*/) { pid_t pid; - int status; - while((pid = waitpid(-1, &status, WUNTRACED | WCONTINUED | WNOHANG)) > 0) ; - if (WIFSIGNALED(status)) { - db_live = 0; - fprintf(stderr,"%5d !!!%s terminated by signal %d\n" - ,getpid(),db_childname,WTERMSIG(status)); - } - if (WIFEXITED(status)) { - db_live = 0; - fprintf(stderr,"%5d ===%s normal exit status=%d\n" + int status = 0; + while((pid = waitpid(-1, &status, WUNTRACED | WCONTINUED | WNOHANG)) > 0) { + + if (WIFSIGNALED(status)) { + db_live = 0; + fprintf(stderr,"%5d !!!%s terminated by signal %d\n" + ,getpid(),db_childname,WTERMSIG(status)); + } + if (WIFEXITED(status)) { + db_live = 0; + fprintf(stderr,"%5d ===%s normal exit status=%d\n" ,getpid(),db_childname,WEXITSTATUS(status)); - } + } #if 0 - if (WIFSTOPPED(status)) { - fprintf(stderr,"%5d ===%s stopped\n",getpid(),db_childname); - } - if (WIFCONTINUED(status)) { - fprintf(stderr,"%5d ===%s continued\n",getpid(),db_childname); - } + if (WIFSTOPPED(status)) { + fprintf(stderr,"%5d ===%s stopped\n",getpid(),db_childname); + } + if (WIFCONTINUED(status)) { + fprintf(stderr,"%5d ===%s continued\n",getpid(),db_childname); + } #endif + } } static int fork_create(int myargc,char *const myargv[])