Merge branch 'collectd-5.5'
authorFlorian Forster <octo@collectd.org>
Thu, 17 Dec 2015 14:19:00 +0000 (15:19 +0100)
committerFlorian Forster <octo@collectd.org>
Thu, 17 Dec 2015 14:19:00 +0000 (15:19 +0100)
1  2 
src/email.c
src/gmond.c
src/perl.c

diff --combined src/email.c
@@@ -50,6 -50,7 +50,6 @@@
  # include <pthread.h>
  #endif
  
 -#include <sys/socket.h>
  #include <sys/un.h>
  #include <sys/select.h>
  
@@@ -305,8 -306,11 +305,11 @@@ static void *collect (void *arg
                                                break;
                                continue;
                        }
+                       if (len < 3) { /* [a-z] ':' '\n' */
+                               continue;
+                       }
  
-                       line[len - 1] = '\0';
+                       line[len - 1] = 0;
  
                        log_debug ("collect: line = '%s'", line);
  
                                bytes = atoi (tmp);
  
                                pthread_mutex_lock (&count_mutex);
-                               type_list_incr (&list_count, type, 1);
+                               type_list_incr (&list_count, type, /* increment = */ 1);
                                pthread_mutex_unlock (&count_mutex);
  
                                if (bytes > 0) {
                                        pthread_mutex_lock (&size_mutex);
-                                       type_list_incr (&list_size, type, bytes);
+                                       type_list_incr (&list_size, type, /* increment = */ bytes);
                                        pthread_mutex_unlock (&size_mutex);
                                }
                        }
                                pthread_mutex_unlock (&score_mutex);
                        }
                        else if ('c' == line[0]) { /* c:<type1>[,<type2>,...] */
-                               char *ptr  = NULL;
-                               char *type = strtok_r (line + 2, ",", &ptr);
-                               do {
-                                       pthread_mutex_lock (&check_mutex);
-                                       type_list_incr (&list_check, type, 1);
-                                       pthread_mutex_unlock (&check_mutex);
-                               } while (NULL != (type = strtok_r (NULL, ",", &ptr)));
+                               char *dummy = line + 2;
+                               char *endptr = NULL;
+                               char *type;
+                               pthread_mutex_lock (&check_mutex);
+                               while ((type = strtok_r (dummy, ",", &endptr)) != NULL)
+                               {
+                                       dummy = NULL;
+                                       type_list_incr (&list_check, type, /* increment = */ 1);
+                               }
+                               pthread_mutex_unlock (&check_mutex);
                        }
                        else {
                                log_err ("collect: unknown type '%c'", line[0]);
@@@ -532,7 -539,7 +538,7 @@@ static void *open_connection (void __at
                }
  
                connection = malloc (sizeof (*connection));
 -              if (connection != NULL)
 +              if (connection == NULL)
                {
                        close (remote);
                        continue;
diff --combined src/gmond.c
@@@ -1,6 -1,6 +1,6 @@@
  /**
   * collectd - src/gmond.c
-  * Copyright (C) 2009,2010  Florian octo Forster
+  * Copyright (C) 2009-2015  Florian octo Forster
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
@@@ -33,6 -33,9 +33,6 @@@
  #if HAVE_PTHREAD_H
  # include <pthread.h>
  #endif
 -#if HAVE_SYS_SOCKET_H
 -# include <sys/socket.h>
 -#endif
  #if HAVE_NETDB_H
  # include <netdb.h>
  #endif
@@@ -80,12 -83,12 +80,12 @@@ typedef struct staging_entry_s staging_
  
  struct metric_map_s
  {
 -  char *ganglia_name;
 -  char *type;
 -  char *type_instance;
 -  char *ds_name;
 -  int   ds_type;
 -  int   ds_index;
 +  char  *ganglia_name;
 +  char  *type;
 +  char  *type_instance;
 +  char  *ds_name;
 +  int    ds_type;
 +  size_t ds_index;
  };
  typedef struct metric_map_s metric_map_t;
  
@@@ -163,7 -166,7 +163,7 @@@ static metric_map_t *metric_lookup (con
      return (NULL);
  
    /* Look up the DS type and ds_index. */
 -  if ((map[i].ds_type < 0) || (map[i].ds_index < 0)) /* {{{ */
 +  if (map[i].ds_type < 0) /* {{{ */
    {
      const data_set_t *ds;
  
      }
      else
      {
 -      int j;
 +      size_t j;
  
        for (j = 0; j < ds->ds_num; j++)
          if (strcasecmp (ds->ds[j].name, map[i].ds_name) == 0)
@@@ -288,8 -291,14 +288,14 @@@ static int create_sockets (socket_entry
      {
        int yes = 1;
  
-       setsockopt (sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR,
+       status = setsockopt (sockets[sockets_num].fd, SOL_SOCKET, SO_REUSEADDR,
            (void *) &yes, sizeof (yes));
+       if (status != 0)
+       {
+         char errbuf[1024];
+         WARNING ("gmond plugin: setsockopt(2) failed: %s",
+                  sstrerror (errno, errbuf, sizeof (errbuf)));
+       }
      }
  
      status = bind (sockets[sockets_num].fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
@@@ -407,10 -416,19 +413,19 @@@ static int request_meta_data (const cha
  
    pthread_mutex_lock (&mc_send_sockets_lock);
    for (i = 0; i < mc_send_sockets_num; i++)
-     sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size,
+   {
+     ssize_t status = sendto (mc_send_sockets[i].fd, buffer, (size_t) buffer_size,
          /* flags = */ 0,
          (struct sockaddr *) &mc_send_sockets[i].addr,
          mc_send_sockets[i].addrlen);
+     if (status == -1)
+     {
+       char errbuf[1024];
+       ERROR ("gmond plugin: sendto(2) failed: %s",
+              sstrerror (errno, errbuf, sizeof (errbuf)));
+       continue;
+     }
+   }
    pthread_mutex_unlock (&mc_send_sockets_lock);
  
    sfree (msg.Ganglia_metadata_msg_u.grequest.metric_id.host);
@@@ -476,39 -494,9 +491,9 @@@ static staging_entry_t *staging_entry_g
    return (se);
  } /* }}} staging_entry_t *staging_entry_get */
  
- static int staging_entry_submit (const char *host, const char *name, /* {{{ */
-     staging_entry_t *se)
- {
-   value_list_t vl;
-   value_t values[se->vl.values_len];
-   if (se->vl.interval == 0)
-   {
-     /* No meta data has been received for this metric yet. */
-     se->flags = 0;
-     pthread_mutex_unlock (&staging_lock);
-     request_meta_data (host, name);
-     return (0);
-   }
-   se->flags = 0;
-   memcpy (values, se->vl.values, sizeof (values));
-   memcpy (&vl, &se->vl, sizeof (vl));
-   /* Unlock before calling `plugin_dispatch_values'.. */
-   pthread_mutex_unlock (&staging_lock);
-   vl.values = values;
-   plugin_dispatch_values (&vl);
-   return (0);
- } /* }}} int staging_entry_submit */
  static int staging_entry_update (const char *host, const char *name, /* {{{ */
      const char *type, const char *type_instance,
 -    int ds_index, int ds_type, value_t value)
 +    size_t ds_index, int ds_type, value_t value)
  {
    const data_set_t *ds;
    staging_entry_t *se;
  
    if (ds->ds_num <= ds_index)
    {
 -    ERROR ("gmond plugin: Invalid index %i: %s has only %i data source(s).",
 +    ERROR ("gmond plugin: Invalid index %zu: %s has only %zu data source(s).",
          ds_index, ds->type, ds->ds_num);
      return (-1);
    }
  
    se->flags |= (0x01 << ds_index);
  
-   /* Check if all values have been set and submit if so. */
-   if (se->flags == ((0x01 << se->vl.values_len) - 1))
+   /* Check if all data sources have been set. If not, return here. */
+   if (se->flags != ((0x01 << se->vl.values_len) - 1))
    {
-     /* `staging_lock' is unlocked in `staging_entry_submit'. */
-     staging_entry_submit (host, name, se);
+     pthread_mutex_unlock (&staging_lock);
+     return (0);
    }
-   else
+   /* Check if the interval of this metric is known. If not, request meta data
+    * and return. */
+   if (se->vl.interval == 0)
    {
+     /* No meta data has been received for this metric yet. */
+     se->flags = 0;
      pthread_mutex_unlock (&staging_lock);
+     request_meta_data (host, name);
+     return (0);
    }
  
+   plugin_dispatch_values (&se->vl);
+   se->flags = 0;
+   pthread_mutex_unlock (&staging_lock);
    return (0);
  } /* }}} int staging_entry_update */
  
diff --combined src/perl.c
@@@ -301,32 -301,33 +301,32 @@@ static int hv2data_source (pTHX_ HV *ha
        return 0;
  } /* static int hv2data_source (HV *, data_source_t *) */
  
 -static int av2value (pTHX_ char *name, AV *array, value_t *value, int len)
 +/* av2value converts at most "len" elements from "array" to "value". Returns the
 + * number of elements converted or zero on error. */
 +static size_t av2value (pTHX_ char *name, AV *array, value_t *value, size_t array_len)
  {
        const data_set_t *ds;
 +      size_t i;
  
 -      int i = 0;
 -
 -      if ((NULL == name) || (NULL == array) || (NULL == value))
 -              return -1;
 -
 -      if (av_len (array) < len - 1)
 -              len = av_len (array) + 1;
 -
 -      if (0 >= len)
 -              return -1;
 +      if ((NULL == name) || (NULL == array) || (NULL == value) || (array_len == 0))
 +              return 0;
  
        ds = plugin_get_ds (name);
        if (NULL == ds) {
                log_err ("av2value: Unknown dataset \"%s\"", name);
 -              return -1;
 +              return 0;
        }
  
 -      if (ds->ds_num < len) {
 -              log_warn ("av2value: Value length exceeds data set length.");
 -              len = ds->ds_num;
 +      if (array_len < ds->ds_num) {
 +              log_warn ("av2value: array does not contain enough elements for type \"%s\": got %zu, want %zu",
 +                              name, array_len, ds->ds_num);
 +              return 0;
 +      } else if (array_len > ds->ds_num) {
 +              log_warn ("av2value: array contains excess elements for type \"%s\": got %zu, want %zu",
 +                              name, array_len, ds->ds_num);
        }
  
 -      for (i = 0; i < len; ++i) {
 +      for (i = 0; i < ds->ds_num; ++i) {
                SV **tmp = av_fetch (array, i, 0);
  
                if (NULL != tmp) {
                                value[i].absolute = SvIV (*tmp);
                }
                else {
 -                      return -1;
 +                      return 0;
                }
        }
 -      return len;
 -} /* static int av2value (char *, AV *, value_t *, int) */
 +
 +      return ds->ds_num;
 +} /* static size_t av2value (char *, AV *, value_t *, size_t) */
  
  /*
   * value list:
@@@ -380,14 -380,16 +380,14 @@@ static int hv2value_list (pTHX_ HV *has
  
        {
                AV  *array = (AV *)SvRV (*tmp);
 -              int len    = av_len (array) + 1;
 -
 -              if (len <= 0)
 +              /* av_len returns the highest index, not the actual length. */
 +              size_t array_len = (size_t) (av_len (array) + 1);
 +              if (array_len == 0)
                        return -1;
  
 -              vl->values     = (value_t *)smalloc (len * sizeof (value_t));
 -              vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp),
 -                              vl->values, len);
 -
 -              if (-1 == vl->values_len) {
 +              vl->values     = calloc (array_len, sizeof (*vl->values));
 +              vl->values_len = av2value (aTHX_ vl->type, (AV *)SvRV (*tmp), vl->values, array_len);
 +              if (vl->values_len == 0) {
                        sfree (vl->values);
                        return -1;
                }
@@@ -602,7 -604,7 +602,7 @@@ static int hv2notification (pTHX_ HV *h
  
  static int data_set2av (pTHX_ data_set_t *ds, AV *array)
  {
 -      int i = 0;
 +      size_t i;
  
        if ((NULL == ds) || (NULL == array))
                return -1;
  static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash)
  {
        AV *values = NULL;
 -
 -      int i   = 0;
 -      int len = 0;
 +      size_t i;
  
        if ((NULL == vl) || (NULL == ds) || (NULL == hash))
                return -1;
  
 -      len = vl->values_len;
 -
 -      if (ds->ds_num < len) {
 -              log_warn ("value2av: Value length exceeds data set length.");
 -              len = ds->ds_num;
 -      }
 -
        values = newAV ();
 -      av_extend (values, len - 1);
 +      /* av_extend takes the last *index* to which the array should be extended. */
 +      av_extend (values, vl->values_len - 1);
  
 -      for (i = 0; i < len; ++i) {
 +      assert (ds->ds_num == vl->values_len);
 +      for (i = 0; i < vl->values_len; ++i) {
                SV *val = NULL;
  
                if (DS_TYPE_COUNTER == ds->ds[i].type)
@@@ -1199,10 -1208,7 +1199,10 @@@ static void c_ithread_destructor (void 
  
        /* the ithread no longer exists */
        if (NULL == t)
 +      {
 +              pthread_mutex_unlock (&perl_threads->mutex);
                return;
 +      }
  
        c_ithread_destroy (ithread);
  
@@@ -2509,7 -2515,10 +2509,10 @@@ static int perl_config (oconfig_item_t 
                int current_status = 0;
  
                if (NULL != perl_threads)
-                       aTHX = PERL_GET_CONTEXT;
+               {
+                       if ((aTHX = PERL_GET_CONTEXT) == NULL)
+                               return -1;
+               }
  
                if (0 == strcasecmp (c->key, "LoadPlugin"))
                        current_status = perl_config_loadplugin (aTHX_ c);