From: Florian Forster Date: Mon, 18 Aug 2014 07:50:34 +0000 (+0200) Subject: Merge branch 'collectd-5.4' X-Git-Tag: collectd-5.5.0~222 X-Git-Url: https://git.octo.it/?p=collectd.git;a=commitdiff_plain;h=103f05e098865196fc5f28df51e99b64fd6b5202;hp=d4547a2861caad836701e70f805f7be68a91272e Merge branch 'collectd-5.4' Conflicts: configure.ac src/curl_json.c src/lvm.c src/write_riemann.c --- diff --git a/ChangeLog b/ChangeLog index 8cd1579e..8112afac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2014-01-26, Version 5.4.1 + * amqp plugin: Add support for RabbitMQ 0.4.x to avoid compiler + warnings. Thanks to Sebastian Harl for implementing this. + * apache / network plugins: Improved initialization order hopefully + resolved gcrypt initialization problems. + * aquaero plugin: The type used to submit fan utilization was fixed. + Thanks to Alex Deymo for the patch. + * cgroups plugin: A small memory leak was fixed. Checking the existence + of a mount option without a value was fixed. More permissive parsing + of the cpuacct.stats file fixes support for some versions of Linux. + Thanks to Marc Fournier for bug reports and patches. + * curl plugin: Fix blocks without an instance. Thanks to + Alexander Golovko for reporting and Sebastian Harl for fixing this. + * curl_json plugin: Potentially invalid memory access has been + sanitized. Thanks to Jim Radford for his patch. + * interface plugin: Fix behavior under FreeBSD 10: Reporting of + per-address statistics caused duplicate updates to the same metric. + Thanks to demon / @trtrmitya for the patch. + * write_graphite plugin: Use TCP to connect to Graphite by default. The + default changed from TCP to UDP between 5.3.1 and 5.4.0, which is a + regression. Thanks to Marc Fournier for fixing this. Reconnect + behavior was improved. Thanks to Michael Hart for his patch. + * zfs_arc plugin: Collect "allocated" and "stolen" on FreeBSD only. + 2013-08-18, Version 5.4.0 * collectd: The "LoadPlugin" config option no longer attempts to load plugins twice. If more than one "LoadPlugin" statement or block is diff --git a/configure.ac b/configure.ac index 92fd8778..0df56782 100644 --- a/configure.ac +++ b/configure.ac @@ -404,6 +404,18 @@ AC_CHECK_HEADERS(linux/if.h, [], [], # include #endif ]) +AC_CHECK_HEADERS(linux/inet_diag.h, [], [], +[ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +#if HAVE_LINUX_INET_DIAG_H +# include +#endif +]) AC_CHECK_HEADERS(linux/netdevice.h, [], [], [ #if HAVE_SYS_TYPES_H @@ -1218,10 +1230,9 @@ if test "x$have_getmntent" = "xgen"; then fi # Check for htonll -AC_MSG_CHECKING([if have htonll defined]) - - have_htonll="no" - AC_LINK_IFELSE([AC_LANG_PROGRAM( +AC_CACHE_CHECK([if have htonll defined], + [c_cv_have_htonll], + AC_LINK_IFELSE([AC_LANG_PROGRAM( [[[ #include #include @@ -1233,12 +1244,14 @@ AC_MSG_CHECKING([if have htonll defined]) return htonll(0); ]]] )], - [ - have_htonll="yes" - AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.]) - ]) - -AC_MSG_RESULT([$have_htonll]) + [c_cv_have_htonll="yes"], + [c_cv_have_htonll="no"] + ) +) +if test "x$c_cv_have_htonll" = "xyes" +then + AC_DEFINE(HAVE_HTONLL, 1, [Define if the function htonll exists.]) +fi # Check for structures AC_CHECK_MEMBERS([struct if_data.ifi_ibytes, struct if_data.ifi_opackets, struct if_data.ifi_ierrors], @@ -1258,6 +1271,13 @@ AC_CHECK_MEMBERS([struct net_device_stats.rx_bytes, struct net_device_stats.tx_p #include #include ]) +AC_CHECK_MEMBERS([struct inet_diag_req.id, struct inet_diag_req.idiag_states], + [AC_DEFINE(HAVE_STRUCT_LINUX_INET_DIAG_REQ, 1, [Define if struct inet_diag_req exists and is usable.])], + [], + [ + #include + ]) + AC_CHECK_MEMBERS([struct ip_mreqn.imr_ifindex], [], [], @@ -1368,8 +1388,8 @@ AC_CHECK_LIB(hal,libhal_device_property_exists, [with_libhal="no"]) if test "x$with_libhal" = "xyes"; then if test "x$PKG_CONFIG" != "x"; then - BUILD_WITH_LIBHAL_CFLAGS="`pkg-config --cflags hal`" - BUILD_WITH_LIBHAL_LIBS="`pkg-config --libs hal`" + BUILD_WITH_LIBHAL_CFLAGS="`$PKG_CONFIG --cflags hal`" + BUILD_WITH_LIBHAL_LIBS="`$PKG_CONFIG --libs hal`" AC_SUBST(BUILD_WITH_LIBHAL_CFLAGS) AC_SUBST(BUILD_WITH_LIBHAL_LIBS) fi @@ -3576,6 +3596,41 @@ fi CPPFLAGS="$SAVE_CPPFLAGS" LDFLAGS="$SAVE_LDFLAGS" AM_CONDITIONAL(BUILD_WITH_LIBRABBITMQ, test "x$with_librabbitmq" = "xyes") + +with_amqp_tcp_socket="no" +if test "x$with_librabbitmq" = "xyes" +then + SAVE_CPPFLAGS="$CPPFLAGS" + SAVE_LDFLAGS="$LDFLAGS" + SAVE_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS $with_librabbitmq_cppflags" + LDFLAGS="$LDFLAGS $with_librabbitmq_ldflags" + LIBS="-lrabbitmq" + + AC_CHECK_HEADERS(amqp_tcp_socket.h amqp_socket.h) + AC_CHECK_FUNC(amqp_tcp_socket_new, [with_amqp_tcp_socket="yes"], [with_amqp_tcp_socket="no"]) + if test "x$with_amqp_tcp_socket" = "xyes" + then + AC_DEFINE(HAVE_AMQP_TCP_SOCKET, 1, + [Define if librabbitmq provides the new TCP socket interface.]) + fi + + AC_CHECK_DECLS(amqp_socket_close, + [amqp_socket_close_decl="yes"], [amqp_socket_close_decl="no"], + [[ +#include +#ifdef HAVE_AMQP_TCP_SOCKET_H +# include +#endif +#ifdef HAVE_AMQP_SOCKET_H +# include +#endif + ]]) + + CPPFLAGS="$SAVE_CPPFLAGS" + LDFLAGS="$SAVE_LDFLAGS" + LIBS="$SAVE_LIBS" +fi # }}} # --with-librdkafka {{{ @@ -3844,18 +3899,20 @@ AC_ARG_WITH(libsigrok, [AS_HELP_STRING([--with-libsigrok@<:@=PREFIX@:>@], [Path with_libsigrok_ldflags="-L$withval/lib" fi fi -],[]) +],[with_libsigrok="yes"]) # libsigrok has a glib dependency if test "x$with_libsigrok" = "xyes" then - if test -z "m4_ifdef([AM_PATH_GLIB_2_0], [yes], [])" - then - with_libsigrok="no (glib not available)" - else - AM_PATH_GLIB_2_0([2.28.0], - [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"]) - fi +m4_ifdef([AM_PATH_GLIB_2_0], + [ + AM_PATH_GLIB_2_0([2.28.0], + [with_libsigrok_cflags="$with_libsigrok_cflags $GLIB_CFLAGS"; with_libsigrok_ldflags="$with_libsigrok_ldflags $GLIB_LIBS"]) + ], + [ + with_libsigrok="no (glib not available)" + ] +) fi # libsigrok headers @@ -4039,8 +4096,8 @@ then if $PKG_CONFIG --exists tokyotyrant then with_libtokyotyrant_cppflags="$with_libtokyotyrant_cppflags `$PKG_CONFIG --cflags tokyotyrant`" - with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `pkg-config --libs-only-L tokyotyrant`" - with_libtokyotyrant_libs="$with_libtokyotyrant_libs `pkg-config --libs-only-l tokyotyrant`" + with_libtokyotyrant_ldflags="$with_libtokyotyrant_ldflags `$PKG_CONFIG --libs-only-L tokyotyrant`" + with_libtokyotyrant_libs="$with_libtokyotyrant_libs `$PKG_CONFIG --libs-only-l tokyotyrant`" fi fi @@ -4557,7 +4614,7 @@ with_libvirt_cflags="" with_libvirt_ldflags="" if test "x$PKG_CONFIG" != "x" then - pkg-config --exists 'libxml-2.0' 2>/dev/null + $PKG_CONFIG --exists 'libxml-2.0' 2>/dev/null if test "$?" = "0" then with_libxml2="yes" @@ -4565,7 +4622,7 @@ then with_libxml2="no (pkg-config doesn't know libxml-2.0)" fi - pkg-config --exists libvirt 2>/dev/null + $PKG_CONFIG --exists libvirt 2>/dev/null if test "$?" = "0" then with_libvirt="yes" @@ -4575,12 +4632,12 @@ then fi if test "x$with_libxml2" = "xyes" then - with_libxml2_cflags="`pkg-config --cflags libxml-2.0`" + with_libxml2_cflags="`$PKG_CONFIG --cflags libxml-2.0`" if test $? -ne 0 then with_libxml2="no" fi - with_libxml2_ldflags="`pkg-config --libs libxml-2.0`" + with_libxml2_ldflags="`$PKG_CONFIG --libs libxml-2.0`" if test $? -ne 0 then with_libxml2="no" @@ -4620,12 +4677,12 @@ if test "x$with_libxml2" = "xyes"; then fi if test "x$with_libvirt" = "xyes" then - with_libvirt_cflags="`pkg-config --cflags libvirt`" + with_libvirt_cflags="`$PKG_CONFIG --cflags libvirt`" if test $? -ne 0 then with_libvirt="no" fi - with_libvirt_ldflags="`pkg-config --libs libvirt`" + with_libvirt_ldflags="`$PKG_CONFIG --libs libvirt`" if test $? -ne 0 then with_libvirt="no" diff --git a/contrib/collection3/etc/collection.conf b/contrib/collection3/etc/collection.conf index 5fe43132..3e19bfcd 100644 --- a/contrib/collection3/etc/collection.conf +++ b/contrib/collection3/etc/collection.conf @@ -7,7 +7,7 @@ GraphWidth 400 RRDTitle "Apache Traffic" RRDVerticalLabel "Bytes/s" RRDFormat "%5.1lf%s" - Color count 0000ff + Color value 0000ff DataSources value @@ -15,7 +15,7 @@ GraphWidth 400 RRDTitle "Apache Traffic" RRDVerticalLabel "Requests/s" RRDFormat "%5.2lf" - Color count 00d000 + Color value 00d000 Module GenericStacked @@ -272,7 +272,7 @@ GraphWidth 400 RRDTitle "Frequency ({type_instance})" RRDVerticalLabel "Hertz" RRDFormat "%4.1lfHz" - Color frequency a000a0 + Color value a000a0 DataSources value @@ -547,7 +547,7 @@ GraphWidth 400 RRDTitle "Percent ({type_instance})" RRDVerticalLabel "Percent" RRDFormat "%4.1lf%%" - Color percent 0000ff + Color value 0000ff DataSources value @@ -705,7 +705,7 @@ GraphWidth 400 RRDTitle "Users ({type_instance}) on {hostname}" RRDVerticalLabel "Users" RRDFormat "%.1lf" - Color users 0000f0 + Color value 0000f0 DataSources value diff --git a/contrib/redhat/collectd.spec b/contrib/redhat/collectd.spec index 6af91e8a..9facca83 100644 --- a/contrib/redhat/collectd.spec +++ b/contrib/redhat/collectd.spec @@ -45,6 +45,7 @@ %{?el6:%global _has_ip_vs_h 1} %{?el6:%global _has_lvm2app_h 1} %{?el6:%global _has_perl_extutils_embed 1} +%{?el6:%global _has_libmodbus 1} # plugins enabled by default %define with_aggregation 0%{!?_without_aggregation:1} @@ -92,6 +93,7 @@ %define with_memcached 0%{!?_without_memcached:1} %define with_memory 0%{!?_without_memory:1} %define with_multimeter 0%{!?_without_multimeter:1} +%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}} %define with_mysql 0%{!?_without_mysql:1} %define with_netlink 0%{!?_without_netlink:1} %define with_network 0%{!?_without_network:1} @@ -422,6 +424,16 @@ The mic plugin collects CPU usage, memory usage, temperatures and power consumption from Intel Many Integrated Core (MIC) CPUs. %endif +%if %{with_modbus} +%package modbus +Summary: modbus plugin for collectd +Group: System Environment/Daemons +Requires: %{name}%{?_isa} = %{version}-%{release} +BuildRequires: libmodbus-devel +%description modbus +The modbus plugin collects values from Modbus/TCP enabled devices +%endif + %if %{with_mysql} %package mysql Summary: MySQL plugin for collectd @@ -997,6 +1009,12 @@ Development files for libcollectdclient %define _with_multimeter --disable-multimeter %endif +%if %{with_modbus} +%define _with_modbus --enable-modbus +%else +%define _with_modbus --disable-modbus +%endif + %if %{with_mysql} %define _with_mysql --enable-mysql %else @@ -2013,6 +2031,9 @@ fi - Enable cgroups, lvm and statsd plugins - Enable (but don't build by default) mic, aquaero and sigrok plugins +* Wed Aug 06 2014 Marc Fournier 5.3.1-2 +- Enabled modbus plugin + * Tue Aug 06 2013 Marc Fournier 5.3.1-1 - New upstream version - Added RHEL5 support: diff --git a/src/Makefile.am b/src/Makefile.am index d25370a5..d7275665 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -520,8 +520,8 @@ if BUILD_PLUGIN_IPTABLES pkglib_LTLIBRARIES += iptables.la iptables_la_SOURCES = iptables.c iptables_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBIPTC_CPPFLAGS) -iptables_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBIPTC_LDFLAGS) -iptables_la_LIBADD = -liptc +iptables_la_LDFLAGS = -module -avoid-version +iptables_la_LIBADD = $(BUILD_WITH_LIBIPTC_LDFLAGS) collectd_LDADD += "-dlopen" iptables.la collectd_DEPENDENCIES += iptables.la endif diff --git a/src/aggregation.c b/src/aggregation.c index 0c0f19d6..8175c66c 100644 --- a/src/aggregation.c +++ b/src/aggregation.c @@ -440,8 +440,7 @@ static int agg_instance_read (agg_instance_t *inst, cdtime_t t) /* {{{ */ /* lookup_class_callback_t for utils_vl_lookup */ static void *agg_lookup_class_callback ( /* {{{ */ - __attribute__((unused)) data_set_t const *ds, - value_list_t const *vl, void *user_class) + data_set_t const *ds, value_list_t const *vl, void *user_class) { return (agg_instance_create (ds, vl, (aggregation_t *) user_class)); } /* }}} void *agg_class_callback */ diff --git a/src/amqp.c b/src/amqp.c index 56718f07..1764129f 100644 --- a/src/amqp.c +++ b/src/amqp.c @@ -38,6 +38,20 @@ #include #include +#ifdef HAVE_AMQP_TCP_SOCKET_H +# include +#endif +#ifdef HAVE_AMQP_SOCKET_H +# include +#endif +#ifdef HAVE_AMQP_TCP_SOCKET +#if defined HAVE_DECL_AMQP_SOCKET_CLOSE && !HAVE_DECL_AMQP_SOCKET_CLOSE +/* rabbitmq-c does not currently ship amqp_socket.h + * and, thus, does not define this function. */ +int amqp_socket_close(amqp_socket_t *); +#endif +#endif + /* Defines for the delivery mode. I have no idea why they're not defined by the * library.. */ #define CAMQP_DM_VOLATILE 1 @@ -392,8 +406,12 @@ static int camqp_setup_queue (camqp_config_t *conf) /* {{{ */ static int camqp_connect (camqp_config_t *conf) /* {{{ */ { amqp_rpc_reply_t reply; - int sockfd; int status; +#ifdef HAVE_AMQP_TCP_SOCKET + amqp_socket_t *socket; +#else + int sockfd; +#endif if (conf->connection != NULL) return (0); @@ -405,6 +423,33 @@ static int camqp_connect (camqp_config_t *conf) /* {{{ */ return (ENOMEM); } +#ifdef HAVE_AMQP_TCP_SOCKET +# define CLOSE_SOCKET() /* amqp_destroy_connection() closes the socket for us */ + /* TODO: add support for SSL using amqp_ssl_socket_new + * and related functions */ + socket = amqp_tcp_socket_new (conf->connection); + if (! socket) + { + ERROR ("amqp plugin: amqp_tcp_socket_new failed."); + amqp_destroy_connection (conf->connection); + conf->connection = NULL; + return (ENOMEM); + } + + status = amqp_socket_open (socket, CONF(conf, host), conf->port); + if (status < 0) + { + char errbuf[1024]; + status *= -1; + ERROR ("amqp plugin: amqp_socket_open failed: %s", + sstrerror (status, errbuf, sizeof (errbuf))); + amqp_destroy_connection (conf->connection); + conf->connection = NULL; + return (status); + } +#else /* HAVE_AMQP_TCP_SOCKET */ +# define CLOSE_SOCKET() close(sockfd) + /* this interface is deprecated as of rabbitmq-c 0.4 */ sockfd = amqp_open_socket (CONF(conf, host), conf->port); if (sockfd < 0) { @@ -417,6 +462,7 @@ static int camqp_connect (camqp_config_t *conf) /* {{{ */ return (status); } amqp_set_sockfd (conf->connection, sockfd); +#endif reply = amqp_login (conf->connection, CONF(conf, vhost), /* channel max = */ 0, @@ -429,7 +475,7 @@ static int camqp_connect (camqp_config_t *conf) /* {{{ */ ERROR ("amqp plugin: amqp_login (vhost = %s, user = %s) failed.", CONF(conf, vhost), CONF(conf, user)); amqp_destroy_connection (conf->connection); - close (sockfd); + CLOSE_SOCKET (); conf->connection = NULL; return (1); } @@ -442,7 +488,7 @@ static int camqp_connect (camqp_config_t *conf) /* {{{ */ ERROR ("amqp plugin: amqp_channel_open failed."); amqp_connection_close (conf->connection, AMQP_REPLY_SUCCESS); amqp_destroy_connection (conf->connection); - close(sockfd); + CLOSE_SOCKET (); conf->connection = NULL; return (1); } diff --git a/src/apache.c b/src/apache.c index 7e4c79bb..ad5975c0 100644 --- a/src/apache.c +++ b/src/apache.c @@ -671,9 +671,18 @@ static int apache_read_host (user_data_t *user_data) /* {{{ */ return (0); } /* }}} int apache_read_host */ +static int apache_init (void) /* {{{ */ +{ + /* Call this while collectd is still single-threaded to avoid + * initialization issues in libgcrypt. */ + curl_global_init (CURL_GLOBAL_SSL); + return (0); +} /* }}} int apache_init */ + void module_register (void) { plugin_register_complex_config ("apache", config); + plugin_register_init ("apache", apache_init); } /* void module_register */ /* vim: set sw=8 noet fdm=marker : */ diff --git a/src/collectd-unixsock.pod b/src/collectd-unixsock.pod index eb1d14fc..b241a9f3 100644 --- a/src/collectd-unixsock.pod +++ b/src/collectd-unixsock.pod @@ -13,6 +13,7 @@ collectd-unixsock - Documentation of collectd's C SocketFile "/path/to/socket" SocketGroup "collectd" SocketPerms "0770" + DeleteSocket false =head1 DESCRIPTION diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 18a74c65..4d5abe0d 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -292,7 +292,7 @@ # # -# +# # CGroup "libvirt" # IgnoreSelected false # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index acd0cbbe..3a8af849 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -494,6 +494,8 @@ possibly filtering or messages. # StoreRates false # GraphitePrefix "collectd." # GraphiteEscapeChar "_" + # GraphiteSeparateInstances false + # GraphiteAlwaysAppendDS false # Receive values from an AMQP broker @@ -647,6 +649,19 @@ In I metric name, dots are used as separators between different metric parts (host, plugin, type). Default is "_" (I). +=item B B|B + +If set to B, the plugin instance and type instance will be in their own +path component, for example C. If set to B (the +default), the plugin and plugin instance (and likewise the type and type +instance) are put into one component, for example C. + +=item B B|B + +If set to B, append the name of the I (DS) to the "metric" +identifier. If set to B (the default), this is only done when there is +more than one DS. + =back =head2 Plugin C @@ -6512,7 +6527,7 @@ instance) are put into one component, for example C. =item B B|B -If set the B, append the name of the I (DS) to the "metric" +If set to B, append the name of the I (DS) to the "metric" identifier. If set to B (the default), this is only done when there is more than one DS. @@ -7387,19 +7402,36 @@ Available options: =item B I Name of the write plugin to which the data should be sent. This option may be -given multiple times to send the data to more than one write plugin. +given multiple times to send the data to more than one write plugin. If the +plugin supports multiple instances, the plugin's instance(s) must also be +specified. =back If no plugin is explicitly specified, the values will be sent to all available write plugins. -Example: +Single-instance plugin example: Plugin "rrdtool" +Multi-instance plugin example: + + + + ... + + + ... + + + ... + + Plugin "write_graphite/foo" + + =item B Starts processing the rules of another chain, see L<"Flow control"> above. If diff --git a/src/common.c b/src/common.c index 93c1ca17..8691d3eb 100644 --- a/src/common.c +++ b/src/common.c @@ -1073,9 +1073,9 @@ int parse_value (const char *value_orig, value_t *ret_value, int ds_type) } if (value == endptr) { - sfree (value); ERROR ("parse_value: Failed to parse string as %s: %s.", DS_TYPE_TO_STRING (ds_type), value); + sfree (value); return -1; } else if ((NULL != endptr) && ('\0' != *endptr)) diff --git a/src/configfile.c b/src/configfile.c index 855681b5..d2a307d9 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -481,6 +481,12 @@ static int cf_ci_replace_child (oconfig_item_t *dst, oconfig_item_t *src, /* Resize the memory containing the children to be big enough to hold * all children. */ + if (dst->children_num + src->children_num - 1 == 0) + { + dst->children_num = 0; + return (0); + } + temp = (oconfig_item_t *) realloc (dst->children, sizeof (oconfig_item_t) * (dst->children_num + src->children_num - 1)); @@ -595,7 +601,8 @@ static int cf_include_all (oconfig_item_t *root, int depth) return (-1); /* Now replace the i'th child in `root' with `new'. */ - cf_ci_replace_child (root, new, i); + if (cf_ci_replace_child (root, new, i) < 0) + return (-1); /* ... and go back to the new i'th child. */ --i; diff --git a/src/curl.c b/src/curl.c index 3e7c5a5d..f605c078 100644 --- a/src/curl.c +++ b/src/curl.c @@ -579,6 +579,7 @@ static int cc_init (void) /* {{{ */ INFO ("curl plugin: No pages have been defined."); return (-1); } + curl_global_init (CURL_GLOBAL_SSL); return (0); } /* }}} int cc_init */ diff --git a/src/curl_json.c b/src/curl_json.c index 6a015902..a84cba04 100644 --- a/src/curl_json.c +++ b/src/curl_json.c @@ -726,7 +726,7 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */ if (status == 0) { user_data_t ud; - char cb_name[DATA_MAX_NAME_LEN]; + char *cb_name; struct timespec interval = { 0, 0 }; CDTIME_T_TO_TIMESPEC (db->interval, &interval); @@ -741,12 +741,13 @@ static int cj_config_add_url (oconfig_item_t *ci) /* {{{ */ ud.data = (void *) db; ud.free_func = cj_free; - ssnprintf (cb_name, sizeof (cb_name), "curl_json-%s-%s", + cb_name = ssnprintf_alloc ("curl_json-%s-%s", db->instance, db->url ? db->url : db->sock); plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read, /* interval = */ (db->interval > 0) ? &interval : NULL, &ud); + sfree (cb_name); } else { @@ -975,9 +976,18 @@ static int cj_read (user_data_t *ud) /* {{{ */ return cj_perform (db); } /* }}} int cj_read */ +static int cj_init (void) /* {{{ */ +{ + /* Call this while collectd is still single-threaded to avoid + * initialization issues in libgcrypt. */ + curl_global_init (CURL_GLOBAL_SSL); + return (0); +} /* }}} int cj_init */ + void module_register (void) { plugin_register_complex_config ("curl_json", cj_config); + plugin_register_init ("curl_json", cj_init); } /* void module_register */ /* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/curl_xml.c b/src/curl_xml.c index 6d36d29d..a743753e 100644 --- a/src/curl_xml.c +++ b/src/curl_xml.c @@ -386,7 +386,7 @@ static int cx_handle_instance_xpath (xmlXPathContextPtr xpath_ctx, /* {{{ */ /* If the base xpath returns more than one block, the result is assumed to be * a table. The `Instance' option is not optional in this case. Check for the * condition and inform the user. */ - if (is_table && (vl->type_instance == NULL)) + if (is_table) { WARNING ("curl_xml plugin: " "Base-XPath %s is a table (more than one result was returned), " @@ -1042,9 +1042,18 @@ static int cx_config (oconfig_item_t *ci) /* {{{ */ return (0); } /* }}} int cx_config */ +static int cx_init (void) /* {{{ */ +{ + /* Call this while collectd is still single-threaded to avoid + * initialization issues in libgcrypt. */ + curl_global_init (CURL_GLOBAL_SSL); + return (0); +} /* }}} int cx_init */ + void module_register (void) { plugin_register_complex_config ("curl_xml", cx_config); + plugin_register_init ("curl_xml", cx_init); } /* void module_register */ /* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/exec.c b/src/exec.c index d56c07fa..cb6844b8 100644 --- a/src/exec.c +++ b/src/exec.c @@ -744,8 +744,8 @@ static void *exec_notification_one (void *arg) /* {{{ */ fprintf (fh, "Severity: %s\n" - "Time: %.3f\n", - severity, CDTIME_T_TO_DOUBLE (n->time)); + "Time: %u\n", + severity, (unsigned int)CDTIME_T_TO_TIME_T(n->time)); /* Print the optional fields */ if (strlen (n->host) > 0) diff --git a/src/lvm.c b/src/lvm.c index 9e245423..82d7f6fe 100644 --- a/src/lvm.c +++ b/src/lvm.c @@ -125,6 +125,10 @@ static void vg_read(vg_t vg, char const *vg_name) } dm_list_iterate_items(lvl, lvs) { + lvm_submit(vg_name, lvm_lv_get_name(lvl->lv), lvm_lv_get_size(lvl->lv)); + } + + dm_list_iterate_items(lvl, lvs) { name = lvm_lv_get_name(lvl->lv); attrs = get_lv_property_string(lvl->lv, "lv_attr"); size = lvm_lv_get_size(lvl->lv); diff --git a/src/network.c b/src/network.c index 5769da79..b1919833 100644 --- a/src/network.c +++ b/src/network.c @@ -501,8 +501,15 @@ static void network_init_gcrypt (void) /* {{{ */ if (gcry_control (GCRYCTL_ANY_INITIALIZATION_P)) return; - gcry_check_version (NULL); /* before calling any other functions */ + /* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html + * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS + * *before* initalizing Libgcrypt with gcry_check_version(), which itself must + * be called before any other gcry_* function. GCRYCTL_ANY_INITIALIZATION_P + * above doesn't count, as it doesn't implicitly initalize Libgcrypt. + * + * tl;dr: keep all these gry_* statements in this exact order please. */ gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); + gcry_check_version (NULL); gcry_control (GCRYCTL_INIT_SECMEM, 32768); gcry_control (GCRYCTL_INITIALIZATION_FINISHED); } /* }}} void network_init_gcrypt */ diff --git a/src/processes.c b/src/processes.c index 210e6f15..5601d290 100644 --- a/src/processes.c +++ b/src/processes.c @@ -223,7 +223,7 @@ static int pagesize; int getprocs64 (void *procsinfo, int sizproc, void *fdsinfo, int sizfd, pid_t *index, int count); int getthrds64( pid_t, void *, int, tid64_t *, int ); #endif -int getargs (struct procentry64 *processBuffer, int bufferLen, char *argsBuffer, int argsLen); +int getargs (void *processBuffer, int bufferLen, char *argsBuffer, int argsLen); #endif /* HAVE_PROCINFO_H */ /* put name of process from config to list_head_g tree diff --git a/src/pyvalues.c b/src/pyvalues.c index 307af175..4a658d06 100644 --- a/src/pyvalues.c +++ b/src/pyvalues.c @@ -767,7 +767,7 @@ static void Values_dealloc(PyObject *self) { } static PyMemberDef Values_members[] = { - {"interval", T_INT, offsetof(Values, interval), 0, interval_doc}, + {"interval", T_DOUBLE, offsetof(Values, interval), 0, interval_doc}, {"values", T_OBJECT_EX, offsetof(Values, values), 0, values_doc}, {"meta", T_OBJECT_EX, offsetof(Values, meta), 0, meta_doc}, {NULL} diff --git a/src/snmp.c b/src/snmp.c index 3be2ae26..7d6e0a10 100644 --- a/src/snmp.c +++ b/src/snmp.c @@ -1618,6 +1618,10 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data) snmp_free_pdu (res); res = NULL; + if (req != NULL) + snmp_free_pdu (req); + req = NULL; + if (status == 0) csnmp_dispatch_table (host, data, instance_list_head, value_list_head); diff --git a/src/tcpconns.c b/src/tcpconns.c index 80435dbe..5a042314 100644 --- a/src/tcpconns.c +++ b/src/tcpconns.c @@ -74,7 +74,9 @@ /* sys/socket.h is necessary to compile when using netlink on older systems. */ # include # include +#if HAVE_LINUX_INET_DIAG_H # include +#endif # include # include /* #endif KERNEL_LINUX */ @@ -137,10 +139,12 @@ #endif /* KERNEL_AIX */ #if KERNEL_LINUX +#if HAVE_STRUCT_LINUX_INET_DIAG_REQ struct nlreq { struct nlmsghdr nlh; struct inet_diag_req r; }; +#endif static const char *tcp_state[] = { @@ -276,7 +280,12 @@ static int port_collect_listening = 0; static port_entry_t *port_list_head = NULL; #if KERNEL_LINUX +#if HAVE_STRUCT_LINUX_INET_DIAG_REQ +/* This depends on linux inet_diag_req because if this structure is missing, + * sequence_number is useless and we get a compilation warning. + */ static uint32_t sequence_number = 0; +#endif enum { @@ -446,6 +455,7 @@ static int conn_handle_ports (uint16_t port_local, uint16_t port_remote, uint8_t * zero on other errors. */ static int conn_read_netlink (void) { +#if HAVE_STRUCT_LINUX_INET_DIAG_REQ int fd; struct sockaddr_nl nladdr; struct nlreq req; @@ -574,6 +584,9 @@ static int conn_read_netlink (void) /* Not reached because the while() loop above handles the exit condition. */ return (0); +#else + return (1); +#endif /* HAVE_STRUCT_LINUX_INET_DIAG_REQ */ } /* int conn_read_netlink */ static int conn_handle_line (char *buffer) diff --git a/src/utils_vl_lookup.c b/src/utils_vl_lookup.c index 01d33ffe..75c02061 100644 --- a/src/utils_vl_lookup.c +++ b/src/utils_vl_lookup.c @@ -26,6 +26,7 @@ #include "collectd.h" +#include #include #include "common.h" @@ -86,6 +87,7 @@ struct user_obj_s struct user_class_s { + pthread_mutex_t lock; void *user_class; identifier_match_t match; user_obj_t *user_obj_list; /* list of user_obj */ @@ -191,6 +193,7 @@ static int lu_copy_ident_to_match (identifier_match_t *match, /* {{{ */ return (0); } /* }}} int lu_copy_ident_to_match */ +/* user_class->lock must be held when calling this function */ static void *lu_create_user_obj (lookup_t *obj, /* {{{ */ data_set_t const *ds, value_list_t const *vl, user_class_t *user_class) @@ -245,6 +248,7 @@ static void *lu_create_user_obj (lookup_t *obj, /* {{{ */ return (user_obj); } /* }}} void *lu_create_user_obj */ +/* user_class->lock must be held when calling this function */ static user_obj_t *lu_find_user_obj (user_class_t *user_class, /* {{{ */ value_list_t const *vl) { @@ -294,14 +298,17 @@ static int lu_handle_user_class (lookup_t *obj, /* {{{ */ || !lu_part_matches (&user_class->match.host, vl->host)) return (1); + pthread_mutex_lock (&user_class->lock); user_obj = lu_find_user_obj (user_class, vl); if (user_obj == NULL) { /* call lookup_class_callback_t() and insert into the list of user objects. */ user_obj = lu_create_user_obj (obj, ds, vl, user_class); + pthread_mutex_unlock (&user_class->lock); if (user_obj == NULL) return (-1); } + pthread_mutex_unlock (&user_class->lock); status = obj->cb_user_obj (ds, vl, user_class->user_class, user_obj->user_obj); @@ -402,7 +409,7 @@ static int lu_add_by_plugin (by_type_entry_t *by_type, /* {{{ */ identifier_match_t const *match = &user_class_list->entry.match; /* Lookup user_class_list from the per-plugin structure. If this is the first - * user_class to be added, the blocks return immediately. Otherwise they will + * user_class to be added, the block returns immediately. Otherwise they will * set "ptr" to non-NULL. */ if (match->plugin.is_regex) { @@ -487,6 +494,7 @@ static void lu_destroy_user_class_list (lookup_t *obj, /* {{{ */ lu_destroy_user_obj (obj, user_class_list->entry.user_obj_list); user_class_list->entry.user_obj_list = NULL; + pthread_mutex_destroy (&user_class_list->entry.lock); sfree (user_class_list); user_class_list = next; @@ -599,6 +607,7 @@ int lookup_add (lookup_t *obj, /* {{{ */ return (ENOMEM); } memset (user_class_obj, 0, sizeof (*user_class_obj)); + pthread_mutex_init (&user_class_obj->entry.lock, /* attr = */ NULL); user_class_obj->entry.user_class = user_class; lu_copy_ident_to_match (&user_class_obj->entry.match, ident, group_by); user_class_obj->entry.user_obj_list = NULL; diff --git a/src/write_http.c b/src/write_http.c index aabca3e9..eee5a1c6 100644 --- a/src/write_http.c +++ b/src/write_http.c @@ -601,9 +601,18 @@ static int wh_config (oconfig_item_t *ci) /* {{{ */ return (0); } /* }}} int wh_config */ +static int wh_init (void) /* {{{ */ +{ + /* Call this while collectd is still single-threaded to avoid + * initialization issues in libgcrypt. */ + curl_global_init (CURL_GLOBAL_SSL); + return (0); +} /* }}} int wh_init */ + void module_register (void) /* {{{ */ { plugin_register_complex_config ("write_http", wh_config); + plugin_register_init ("write_http", wh_init); } /* }}} void module_register */ /* vim: set fdm=marker sw=8 ts=8 tw=78 et : */ diff --git a/src/write_riemann.c b/src/write_riemann.c index 78f01c05..b59c3e35 100644 --- a/src/write_riemann.c +++ b/src/write_riemann.c @@ -51,8 +51,8 @@ struct riemann_host { #define F_CONNECT 0x01 uint8_t flags; pthread_mutex_t lock; - _Bool notifications; - _Bool check_thresholds; + _Bool notifications; + _Bool check_thresholds; _Bool store_rates; _Bool always_append_ds; char *node; @@ -97,7 +97,7 @@ static void riemann_event_protobuf_free (Event *event) /* {{{ */ sfree (event); } /* }}} void riemann_event_protobuf_free */ -static void riemann_msg_protobuf_free (Msg *msg) /* {{{ */ +static void riemann_msg_protobuf_free(Msg *msg) /* {{{ */ { size_t i; @@ -319,7 +319,7 @@ static int riemann_event_add_tag (Event *event, char const *tag) /* {{{ */ return (strarray_add (&event->tags, &event->n_tags, tag)); } /* }}} int riemann_event_add_tag */ -static int riemann_event_add_attribute (Event *event, /* {{{ */ +static int riemann_event_add_attribute(Event *event, /* {{{ */ char const *key, char const *value) { Attribute **new_attributes; @@ -352,7 +352,7 @@ static int riemann_event_add_attribute (Event *event, /* {{{ */ return (0); } /* }}} int riemann_event_add_attribute */ -static Msg *riemann_notification_to_protobuf (struct riemann_host *host, /* {{{ */ +static Msg *riemann_notification_to_protobuf(struct riemann_host *host, /* {{{ */ notification_t const *n) { Msg *msg; @@ -459,7 +459,7 @@ static Msg *riemann_notification_to_protobuf (struct riemann_host *host, /* {{{ return (msg); } /* }}} Msg *riemann_notification_to_protobuf */ -static Event *riemann_value_to_protobuf (struct riemann_host const *host, /* {{{ */ +static Event *riemann_value_to_protobuf(struct riemann_host const *host, /* {{{ */ data_set_t const *ds, value_list_t const *vl, size_t index, gauge_t const *rates, @@ -484,22 +484,22 @@ static Event *riemann_value_to_protobuf (struct riemann_host const *host, /* {{{ event->time = CDTIME_T_TO_TIME_T (vl->time); event->has_time = 1; - if (host->check_thresholds) { - switch (status) { - case STATE_OKAY: - event->state = strdup("ok"); - break; - case STATE_ERROR: - event->state = strdup("critical"); - break; - case STATE_WARNING: - event->state = strdup("warning"); - break; - case STATE_MISSING: - event->state = strdup("unknown"); - break; - } - } + if (host->check_thresholds) { + switch (status) { + case STATE_OKAY: + event->state = strdup("ok"); + break; + case STATE_ERROR: + event->state = strdup("critical"); + break; + case STATE_WARNING: + event->state = strdup("warning"); + break; + case STATE_MISSING: + event->state = strdup("unknown"); + break; + } + } ttl = CDTIME_T_TO_DOUBLE (vl->interval) * host->ttl_factor; event->ttl = (float) ttl; @@ -645,8 +645,8 @@ static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ struct riemann_host *host = ud->data; Msg *msg; - if (!host->notifications) - return 0; + if (!host->notifications) + return 0; msg = riemann_notification_to_protobuf (host, n); if (msg == NULL) @@ -670,8 +670,8 @@ static int riemann_write(const data_set_t *ds, /* {{{ */ struct riemann_host *host = ud->data; Msg *msg; - if (host->check_thresholds) - write_riemann_threshold_check(ds, vl, statuses); + if (host->check_thresholds) + write_riemann_threshold_check(ds, vl, statuses); msg = riemann_value_list_to_protobuf (host, ds, vl, statuses); if (msg == NULL) return (-1); @@ -725,8 +725,8 @@ static int riemann_config_node(oconfig_item_t *ci) /* {{{ */ host->reference_count = 1; host->node = NULL; host->service = NULL; - host->notifications = 1; - host->check_thresholds = 0; + host->notifications = 1; + host->check_thresholds = 0; host->store_rates = 1; host->always_append_ds = 0; host->use_tcp = 0; @@ -751,14 +751,14 @@ static int riemann_config_node(oconfig_item_t *ci) /* {{{ */ status = cf_util_get_string (child, &host->node); if (status != 0) break; - } else if (strcasecmp ("Notifications", child->key) == 0) { - status = cf_util_get_boolean(child, &host->notifications); - if (status != 0) - break; - } else if (strcasecmp ("CheckThresholds", child->key) == 0) { - status = cf_util_get_boolean(child, &host->check_thresholds); - if (status != 0) - break; + } else if (strcasecmp ("Notifications", child->key) == 0) { + status = cf_util_get_boolean(child, &host->notifications); + if (status != 0) + break; + } else if (strcasecmp ("CheckThresholds", child->key) == 0) { + status = cf_util_get_boolean(child, &host->check_thresholds); + if (status != 0) + break; } else if (strcasecmp ("Port", child->key) == 0) { status = cf_util_get_service (child, &host->service); if (status != 0) { @@ -928,7 +928,7 @@ static int riemann_config(oconfig_item_t *ci) /* {{{ */ child->key); } } - return 0; + return (0); } /* }}} int riemann_config */ void module_register(void) diff --git a/version-gen.sh b/version-gen.sh index 7fbc8671..6b5e40e5 100755 --- a/version-gen.sh +++ b/version-gen.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -DEFAULT_VERSION="5.4.0.git" +DEFAULT_VERSION="5.4.1.git" VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"