write_graphite plugin: Fix locking.
authorFlorian Forster <octo@collectd.org>
Fri, 3 Feb 2012 09:54:58 +0000 (10:54 +0100)
committerFlorian Forster <octo@collectd.org>
Fri, 3 Feb 2012 09:54:58 +0000 (10:54 +0100)
wg_send_buffer() is called from wg_flush_nolock(). When calling
wg_flush_nolock(), the thread has to hold cb->send_lock. Locking it again
will fail, but this condition is not checked for. Then the lock is
released twice which may result in concurrency issues.

Change-Id: Ie3062d50e6545adeb95b3a1938837c1f26835a56

src/write_graphite.c

index de460d7..6b16bec 100644 (file)
@@ -120,20 +120,15 @@ static int wg_send_buffer (struct wg_callback *cb)
                 status,
                 strerror (errno));
 
-        pthread_mutex_trylock (&cb->send_lock);
-
-        DEBUG ("write_graphite plugin: closing socket and restting fd "
-                "so reinit will occur");
         close (cb->sock_fd);
         cb->sock_fd = -1;
 
-        pthread_mutex_unlock (&cb->send_lock);
-
         return (-1);
     }
     return (0);
 }
 
+/* NOTE: You must hold cb->send_lock when calling this function! */
 static int wg_flush_nolock (cdtime_t timeout, struct wg_callback *cb)
 {
     int status;
@@ -240,14 +235,20 @@ static void wg_callback_free (void *data)
 
     cb = data;
 
+    pthread_mutex_lock (&cb->send_lock);
+
     wg_flush_nolock (/* timeout = */ 0, cb);
 
     close(cb->sock_fd);
+    cb->sock_fd = -1;
+
     sfree(cb->node);
     sfree(cb->service);
     sfree(cb->prefix);
     sfree(cb->postfix);
 
+    pthread_mutex_destroy (&cb->send_lock);
+
     sfree(cb);
 }