Преглед изворни кода

[Fix] Try to avoid race condition when using rrd

tags/1.4.0
Vsevolod Stakhov пре 7 година
родитељ
комит
74532cb312
3 измењених фајлова са 59 додато и 13 уклоњено
  1. 1
    0
      src/controller.c
  2. 57
    13
      src/libutil/rrd.c
  3. 1
    0
      src/libutil/rrd.h

+ 1
- 0
src/controller.c Прегледај датотеку

@@ -2668,6 +2668,7 @@ rspamd_controller_on_terminate (struct rspamd_worker *worker)
rspamd_controller_store_saved_stats (ctx);

if (ctx->rrd) {
msg_info ("closing rrd file: %s", ctx->rrd->filename);
event_del (ctx->rrd_event);
rspamd_rrd_close (ctx->rrd);
}

+ 57
- 13
src/libutil/rrd.c Прегледај датотеку

@@ -350,6 +350,40 @@ rspamd_rrd_calculate_checksum (struct rspamd_rrd_file *file)
}
}

static int
rspamd_rrd_open_exclusive (const gchar *filename)
{
struct timespec sleep_ts = {
.tv_sec = 0,
.tv_nsec = 1000000
};
gint fd;

fd = open (filename, O_RDWR);

if (fd == -1) {
return -1;
}

for (;;) {
if (rspamd_file_lock (fd, TRUE) == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
nanosleep (&sleep_ts, NULL);
continue;
}
else {
close (fd);
return -1;
}
}
else {
break;
}
}

return fd;
};

/**
* Open completed or incompleted rrd file
* @param filename
@@ -376,7 +410,7 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err)
}

/* Open file */
fd = open (filename, O_RDWR);
fd = rspamd_rrd_open_exclusive (filename);
if (fd == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd open error: %s", strerror (errno));
@@ -386,14 +420,17 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err)
if (fstat (fd, &st) == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno));
rspamd_file_unlock (fd, FALSE);
close (fd);
return FALSE;
}
/* Mmap file */
file->size = st.st_size;
if ((file->map =
mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
0)) == MAP_FAILED) {
mmap (NULL, st.st_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0)) == MAP_FAILED) {

rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), ENOMEM, "mmap failed: %s", strerror (errno));
@@ -401,7 +438,7 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err)
return NULL;
}

close (fd);
file->fd = fd;

/* Adjust pointers */
rspamd_rrd_adjust_pointers (file, completed);
@@ -462,7 +499,7 @@ rspamd_rrd_create (const gchar *filename,
guint i, j;

/* Open file */
fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
fd = open (filename, O_RDWR | O_CREAT | O_EXCL, 0644);
if (fd == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd create error: %s",
@@ -470,6 +507,8 @@ rspamd_rrd_create (const gchar *filename,
return NULL;
}

rspamd_file_lock (fd, FALSE);

/* Fill header */
memset (&head, 0, sizeof (head));
head.rra_cnt = rra_count;
@@ -480,6 +519,7 @@ rspamd_rrd_create (const gchar *filename,
head.float_cookie = RRD_FLOAT_COOKIE;

if (write (fd, &head, sizeof (head)) != sizeof (head)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s", strerror (errno));
@@ -493,6 +533,7 @@ rspamd_rrd_create (const gchar *filename,
memset (&ds.par, 0, sizeof (ds.par));
for (i = 0; i < ds_count; i++) {
if (write (fd, &ds, sizeof (ds)) != sizeof (ds)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -508,6 +549,7 @@ rspamd_rrd_create (const gchar *filename,
memset (&rra.par, 0, sizeof (rra.par));
for (i = 0; i < rra_count; i++) {
if (write (fd, &rra, sizeof (rra)) != sizeof (rra)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -522,6 +564,7 @@ rspamd_rrd_create (const gchar *filename,
lh.last_up_usec = (glong)((initial_ticks - lh.last_up) * 1e6f);

if (write (fd, &lh, sizeof (lh)) != sizeof (lh)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s", strerror (errno));
@@ -537,6 +580,7 @@ rspamd_rrd_create (const gchar *filename,

for (i = 0; i < ds_count; i++) {
if (write (fd, &pdp, sizeof (pdp)) != sizeof (pdp)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -554,6 +598,7 @@ rspamd_rrd_create (const gchar *filename,
for (i = 0; i < rra_count; i++) {
for (j = 0; j < ds_count; j++) {
if (write (fd, &cdp, sizeof (cdp)) != sizeof (cdp)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -567,6 +612,7 @@ rspamd_rrd_create (const gchar *filename,
memset (&rra_ptr, 0, sizeof (rra_ptr));
for (i = 0; i < rra_count; i++) {
if (write (fd, &rra_ptr, sizeof (rra_ptr)) != sizeof (rra_ptr)) {
rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -575,7 +621,9 @@ rspamd_rrd_create (const gchar *filename,
}
}

rspamd_file_unlock (fd, FALSE);
close (fd);

new = rspamd_rrd_open_common (filename, FALSE, err);

return new;
@@ -643,18 +691,13 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err)
gdouble vbuf[1024];
struct stat st;

if (file == NULL || file->filename == NULL) {
if (file == NULL || file->filename == NULL || file->fd == -1) {
g_set_error (err,
rrd_error_quark (), EINVAL, "rrd add rra failed: wrong arguments");
return FALSE;
}

fd = open (file->filename, O_RDWR);
if (fd == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd open error: %s", strerror (errno));
return FALSE;
}
fd = file->fd;

if (lseek (fd, 0, SEEK_END) == -1) {
g_set_error (err,
@@ -710,7 +753,7 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err)
g_slice_free1 (sizeof (struct rspamd_rrd_file), file);
return FALSE;
}
close (fd);
/* Adjust pointers */
rspamd_rrd_adjust_pointers (file, TRUE);

@@ -1214,6 +1257,7 @@ rspamd_rrd_close (struct rspamd_rrd_file * file)
}

munmap (file->map, file->size);
close (file->fd);
g_free (file->filename);
g_free (file->id);


+ 1
- 0
src/libutil/rrd.h Прегледај датотеку

@@ -204,6 +204,7 @@ struct rspamd_rrd_file {
gsize size; /* its size */
gboolean finalized;
gchar *id;
gint fd;
};



Loading…
Откажи
Сачувај