From 01e00e93952f48469fc66be9a3a18017c0dd9298 Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Sat, 9 Jul 2016 09:44:51 +0300 Subject: [PATCH] Convert rrdtool to use work queues instead of forks 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 --- process.c | 15 --------------- rrdtool.c | 26 +++++++++++++------------- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/process.c b/process.c index 77ec174..8d3d18f 100644 --- 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; } diff --git a/rrdtool.c b/rrdtool.c index df9b5c8..58c0f57 100644 --- 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); } /* -- 2.44.0