]> git.itanic.dy.fi Git - rrdd/commitdiff
rrdtool_draw_image: Avoid corrupting image files
authorTimo Kokkonen <timo.t.kokkonen@iki.fi>
Wed, 11 Apr 2012 17:46:29 +0000 (20:46 +0300)
committerTimo Kokkonen <timo.t.kokkonen@iki.fi>
Wed, 11 Apr 2012 18:00:47 +0000 (21:00 +0300)
As rrdtool is creating the image file it does appear to modify always
the contents of the existing file. This leads to a potential race
condition where someone is reading the current image contents and then
rrdtool changes the contents while the reader is still in the process
of the reading the old contents. If that happens, the image file
appears to be corrupted due to the fact that it contains a mixture of
the old and new image data.

Fix the issue by creating a temporary file where the image is created
and then replacing the target file with the temp file only after
rrdtool has finished drawing all of the image. This ensures reader
will be accessing either the old or new image contents, newer
something that is a mixture of those two.

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

index e341f5a6cb23665da6bf92dfc949fc58c1914965..cb2eb43d827a1f5156ae2df06c8b00be31fe4ca6 100644 (file)
--- a/rrdtool.c
+++ b/rrdtool.c
@@ -38,10 +38,15 @@ int rrdtool_draw_image(struct rrd_image *image)
        int idx = 0, argcnt = 0, i,j;
        char timestamp[256];
        char tmp[256];
+       char tmpfile[256];
        time_t t = time(0);
 
        pr_info("Drawing image %s\n", image->image_filename);
 
+       tmpfile[0] = 0;
+       strncat(tmpfile, image->image_filename, sizeof(tmp) - strlen(tmp) - 1);
+       strncat(tmpfile, ".tmp", sizeof(tmp) - strlen(tmp) - 1);
+
        strftime(tmp, 256, "%d.%m.%Y %T (%Z) ", localtime(&t));
        for (i = 0, j = 0; j < 256;) {
                if (tmp[i] == ':') {
@@ -56,7 +61,7 @@ int rrdtool_draw_image(struct rrd_image *image)
 
        add_arg(args, argcnt, argstr, idx, " ");
        add_arg(args, argcnt, argstr, idx, "graph");
-       add_arg(args, argcnt, argstr, idx, "%s", image->image_filename);
+       add_arg(args, argcnt, argstr, idx, "%s", tmpfile);
 
        add_arg(args, argcnt, argstr, idx, "--start");
        add_arg(args, argcnt, argstr, idx, "%s", image->timestart);
@@ -83,6 +88,8 @@ int rrdtool_draw_image(struct rrd_image *image)
 
        run(cmd, args);
 
+       rename(tmpfile, image->image_filename);
+
        return 0;
 }