]> git.itanic.dy.fi Git - rrdd/commitdiff
process: Improve harvest_zombies
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Tue, 15 May 2012 19:07:18 +0000 (22:07 +0300)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Tue, 15 May 2012 19:07:21 +0000 (22:07 +0300)
Use wait4 instead of waitpid. This makes it possible to get resource
usage information from the child that exited. The user and system time
is printed out for curious developer to inspect.

If a child happens to be stopped or continued, we are now ignoring
those state changes. This prevents zombie processes to be left in case
something special happens to the child.

Further improvement is that it is possible to tell whether the child
was killed with some signal or if it exited with a code.

Signed-off-by: Timo Kokkonen <timo.t.kokkonen@iki.fi>
process.c

index 0632e6c6697abad5aa5ff4a88c9592b3ab12507e..791a3ed620b7de70ee13edae55c08d5c0b7aa4e0 100644 (file)
--- a/process.c
+++ b/process.c
@@ -4,6 +4,8 @@
 #include <sys/select.h>
 #include <sys/epoll.h>
 #include <stdio.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
 
 #include "process.h"
 #include "debug.h"
@@ -346,6 +348,9 @@ int do_fork_limited(void)
 int harvest_zombies(int pid)
 {
        int status;
+       struct rusage rusage;
+       char *status_str = NULL;
+       int code = 0;
 
        if (child_count == 0)
                return 0;
@@ -354,16 +359,28 @@ int harvest_zombies(int pid)
                pr_info("Waiting on pid %d, children left: %d\n", pid, 
                        child_count);
 
-       pid = waitpid(pid, &status, 0);
-       if (pid < 0) {
-               pr_err("Error on wait(): %m\n");
-               child_count--; /* Decrement child count anyway */
-       }
-       else {
-               child_count--;
-               pr_info("pid %d: exit code %d. Children left: %d\n", pid,
-                       status, child_count);
+       do {
+               pid = wait4(pid, &status, 0, &rusage);
+               if (pid < 0) {
+                       pr_err("Error on waitid(): %m\n");
+                       return 0;
+               }
+               /* Wait until the child has become a zombie */
+       } while (!WIFEXITED(status) && !WIFSIGNALED(status));
+
+       child_count--;
+       if (WIFEXITED(status)) {
+               status_str = "exited with status";
+               code = WEXITSTATUS(status);
+       } else if (WIFSIGNALED(status)) {
+               status_str = "killed by signal";
+               code = WTERMSIG(status);
        }
+       pr_info("pid %d: %s %d. Children left: %d\n", pid,
+               status_str, code, child_count);
+       pr_info("pid %d: User time: %ld.%03lds, System %ld.%03lds\n", pid,
+               (long)rusage.ru_utime.tv_sec, rusage.ru_utime.tv_usec / 1000,
+               (long)rusage.ru_stime.tv_sec, rusage.ru_stime.tv_usec / 1000);
 
        return 1;
 }