]> git.itanic.dy.fi Git - rrdd/commitdiff
Convert rrdtool to use work queues instead of forks
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Sat, 9 Jul 2016 06:44:51 +0000 (09:44 +0300)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Sat, 9 Jul 2016 06:49:12 +0000 (09:49 +0300)
Switch to the work queue model. Change is somewhat trivial. The
database update timestamp update is now done before the actual
update. We don't have a mean to distinguis from the fact that we have
initiated an update but not done it yet, so we mark it as "done" and
then queue the update. Without this change the main thread will keep
on queueing the update indefinitely as the worker thread takes too
long to actually mark the update as done.

To ensure the queues work properly, we also need to disable sigchld
handler from the process controller so that it does not get confused
when threads are reaping the childs them selves. This is different
from the previous model where each process required to handle their
own child reaping after fork(). Now we are sharing the signals with
the parent. This is a major simplification on how this works.

The magic sleep on job control init can be removed as well as there
are less forks going on now.

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

index 77ec174945b109872163a96f2786f421f244bed6..8d3d18fdd94de8776b5ee7e8882b7159c98a84e2 100644 (file)
--- a/process.c
+++ b/process.c
@@ -340,12 +340,6 @@ int init_jobcontrol(int max_jobs_requested)
        sigemptyset(&sigmask);
        sigaddset(&sigmask, SIGCHLD);
 
-       /* Block SIGCHLD so that it becomes readable via signalfd */
-       ret = sigprocmask(SIG_BLOCK, &sigmask, NULL);
-       if (ret < 0) {
-               pr_err("Failed to sigprocmask: %m\n");
-       }
-
        signal_handler.fd = signalfd(-1, &sigmask, SFD_CLOEXEC);
        if (job_request_handler.fd < 0) {
                pr_err("Failed to create signal_fd: %m\n");
@@ -398,15 +392,6 @@ no_count_cpus:
        for (i = 0; i < max_jobs; i++)
                pthread_create(&thread[i], NULL, worker_thread, (void *)i);
 
-       /*
-        * Magic sleep. There are too many fork() calls at the moment
-        * so we must ensure our threads don't print anything out
-        * while a fork() is executed. Otherwise the child will
-        * inherit glibc internal locks while they are locked, and
-        * function calls such as printf will deadlock.
-        */
-       sleep(1);
-
        return 0;
 }
 
index df9b5c80fba4f788855b9f0c3fe3ceb888137ee1..58c0f57b069cfcadcc3728f76f4330f836b4e71d 100644 (file)
--- a/rrdtool.c
+++ b/rrdtool.c
@@ -45,10 +45,6 @@ int rrdtool_draw_image(struct rrd_image *image)
        time_t t = time(0);
        const char *updatestr = "Last update %d.%m.%Y %T (%Z)";
 
-       pid = do_fork_limited();
-       if (pid)
-               return pid;
-
        pr_info("Drawing image %s\n", image->image_filename);
 
        tmpfile[0] = 0;
@@ -100,14 +96,15 @@ int rrdtool_draw_image(struct rrd_image *image)
 
        rename(tmpfile, image->image_filename);
 
-       exit(0);
+       return 0;
 }
 
 int rrdtool_draw_images(struct rrd_image **image)
 {
        int i;
        for (i = 0; image[i]; i++)
-               rrdtool_draw_image(image[i]);
+               queue_work(WORK_PRIORITY_LOW, "rrdtool_draw_image",
+                       rrdtool_draw_image, image[i]);
 
        return 0;
 }
@@ -255,7 +252,7 @@ static int write_to_logfile(struct rrd_database *rrd, const char *data)
        return ret < 0 ? ret : 0;
 }
 
-int rrdtool_update_data(struct rrd_database *rrd)
+static int do_rrdtool_update_data(struct rrd_database *rrd)
 {
        int pid;
        char data[RRD_DATA_MAX_LEN + 3]; /* 3 == "N:" + NULL termination */
@@ -270,10 +267,6 @@ int rrdtool_update_data(struct rrd_database *rrd)
        };
        int l;
 
-       rrd->last_update = time(0);
-       if (do_fork())
-               return 0;
-
        l = sprintf(data, "N:");
 
        if (rrd->parser && rrd->parser->parse) {
@@ -297,8 +290,15 @@ int rrdtool_update_data(struct rrd_database *rrd)
        if (rrd->images)
                rrdtool_draw_images(rrd->images);
 
-       while (harvest_zombies(0));
-       exit(0);
+       return 0;
+}
+
+int rrdtool_update_data(struct rrd_database *rrd)
+{
+       rrd->last_update = time(0);
+
+       return queue_work(WORK_PRIORITY_HIGH, "rrdtool_update_data",
+                       do_rrdtool_update_data, rrd);
 }
 
 /*