Attempt to fix collectd/collectd#229 by doing user / group lookups before we fork.
[collectd.git] / src / aggregation.c
index 985fa7c..db33c17 100644 (file)
@@ -192,13 +192,21 @@ static int agg_instance_update (agg_instance_t *inst, /* {{{ */
   gauge_t *rate;
 
   if (ds->ds_num != 1)
-    return (-1);
+  {
+    ERROR ("aggregation plugin: The \"%s\" type (data set) has more than one "
+        "data source. This is currently not supported by this plugin. "
+        "Sorry.", ds->type);
+    return (EINVAL);
+  }
 
   rate = uc_get_rate (ds, vl);
   if (rate == NULL)
   {
-    ERROR ("aggregation plugin: uc_get_rate() failed.");
-    return (-1);
+    char ident[6 * DATA_MAX_NAME_LEN];
+    FORMAT_VL (ident, sizeof (ident), vl);
+    ERROR ("aggregation plugin: Unable to read the current rate of \"%s\".",
+        ident);
+    return (ENOENT);
   }
 
   if (isnan (rate[0]))
@@ -241,6 +249,12 @@ static int agg_instance_read_func (agg_instance_t *inst, /* {{{ */
   status = rate_to_value (&v, rate, state, inst->ds_type, t);
   if (status != 0)
   {
+    /* If this is the first iteration and rate_to_value() was asked to return a
+     * COUNTER or a DERIVE, it will return EAGAIN. Catch this and handle
+     * gracefully. */
+    if (status == EAGAIN)
+      return (0);
+
     WARNING ("aggregation plugin: rate_to_value failed with status %i.",
         status);
     return (-1);
@@ -606,6 +620,18 @@ static int agg_read (void) /* {{{ */
 
   pthread_mutex_lock (&agg_instance_list_lock);
 
+  /* agg_instance_list_head only holds data, after the "write" callback has
+   * been called with a matching value list at least once. So on startup,
+   * there's a race between the aggregations read() and write() callback. If
+   * the read() callback is called first, agg_instance_list_head is NULL and
+   * "success" may be zero. This is expected and should not result in an error.
+   * Therefore we need to handle this case separately. */
+  if (agg_instance_list_head == NULL)
+  {
+    pthread_mutex_unlock (&agg_instance_list_lock);
+    return (0);
+  }
+
   for (this = agg_instance_list_head; this != NULL; this = this->next)
   {
     int status;