X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Fperl.c;h=48374b69b8df5fc041fc4c25732bcd4c691cfff8;hb=448627953cde2f7b3b138f53f4f2c62f0d48b726;hp=b0ab63128ca469b267935aa07d54f4c280217479;hpb=7b56fff886f05d8379bcd4c5885d85001b05a31c;p=collectd.git diff --git a/src/perl.c b/src/perl.c index b0ab6312..48374b69 100644 --- a/src/perl.c +++ b/src/perl.c @@ -2,20 +2,25 @@ * collectd - src/perl.c * Copyright (C) 2007-2009 Sebastian Harl * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; only version 2 of the License is applicable. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. * - * Author: + * Authors: * Sebastian Harl **/ @@ -24,11 +29,12 @@ * interface for collectd plugins written in perl. */ -/* do not automatically get the thread specific perl interpreter */ +/* do not automatically get the thread specific Perl interpreter */ #define PERL_NO_GET_CONTEXT #define DONT_POISON_SPRINTF_YET 1 #include "collectd.h" + #undef DONT_POISON_SPRINTF_YET #include "configfile.h" @@ -41,6 +47,7 @@ #include #if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__ +# undef sprintf # pragma GCC poison sprintf #endif @@ -57,8 +64,6 @@ #include "filter_chain.h" -#include - #if !defined(USE_ITHREADS) # error "Perl does not support ithreads!" #endif /* !defined(USE_ITHREADS) */ @@ -117,7 +122,7 @@ static XS (Collectd_call_by_name); typedef struct c_ithread_s { /* the thread's Perl interpreter */ PerlInterpreter *interp; - _Bool running; /* thread is inside pi */ + _Bool running; /* thread is inside Perl interpreter */ _Bool shutdown; pthread_t pthread; @@ -299,33 +304,31 @@ static int hv2data_source (pTHX_ HV *hash, data_source_t *ds) 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; - 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 (size_t i = 0; i < ds->ds_num; ++i) { SV **tmp = av_fetch (array, i, 0); if (NULL != tmp) { @@ -339,11 +342,12 @@ static int av2value (pTHX_ char *name, AV *array, value_t *value, int len) 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: @@ -378,16 +382,14 @@ static int hv2value_list (pTHX_ HV *hash, value_list_t *vl) { 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; } @@ -425,7 +427,7 @@ static int hv2value_list (pTHX_ HV *hash, value_list_t *vl) static int av2data_set (pTHX_ AV *array, char *name, data_set_t *ds) { - int len, i; + int len; if ((NULL == array) || (NULL == name) || (NULL == ds)) return -1; @@ -437,10 +439,10 @@ static int av2data_set (pTHX_ AV *array, char *name, data_set_t *ds) return -1; } - ds->ds = (data_source_t *)smalloc ((len + 1) * sizeof (data_source_t)); + ds->ds = smalloc ((len + 1) * sizeof (*ds->ds)); ds->ds_num = len + 1; - for (i = 0; i <= len; ++i) { + for (int i = 0; i <= len; ++i) { SV **elem = av_fetch (array, i, 0); if (NULL == elem) { @@ -484,9 +486,8 @@ static int av2notification_meta (pTHX_ AV *array, notification_meta_t **meta) notification_meta_t **m = meta; int len = av_len (array); - int i; - for (i = 0; i <= len; ++i) { + for (int i = 0; i <= len; ++i) { SV **tmp = av_fetch (array, i, 0); HV *hash; @@ -501,7 +502,7 @@ static int av2notification_meta (pTHX_ AV *array, notification_meta_t **meta) hash = (HV *)SvRV (*tmp); - *m = (notification_meta_t *)smalloc (sizeof (**m)); + *m = smalloc (sizeof (**m)); if (NULL == (tmp = hv_fetch (hash, "name", 4, 0))) { log_warn ("av2notification_meta: Skipping invalid " @@ -602,14 +603,12 @@ static int hv2notification (pTHX_ HV *hash, notification_t *n) static int data_set2av (pTHX_ data_set_t *ds, AV *array) { - int i = 0; - if ((NULL == ds) || (NULL == array)) return -1; av_extend (array, ds->ds_num); - for (i = 0; i < ds->ds_num; ++i) { + for (size_t i = 0; i < ds->ds_num; ++i) { HV *source = newHV (); if (NULL == hv_store (source, "name", 4, @@ -638,24 +637,17 @@ static int data_set2av (pTHX_ data_set_t *ds, AV *array) 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) @@ -716,7 +708,6 @@ static int value_list2hv (pTHX_ value_list_t *vl, data_set_t *ds, HV *hash) static int notification_meta2av (pTHX_ notification_meta_t *meta, AV *array) { int meta_num = 0; - int i; while (meta) { ++meta_num; @@ -725,7 +716,7 @@ static int notification_meta2av (pTHX_ notification_meta_t *meta, AV *array) av_extend (array, meta_num); - for (i = 0; NULL != meta; meta = meta->next, ++i) { + for (int i = 0; NULL != meta; meta = meta->next, ++i) { HV *m = newHV (); SV *value; @@ -812,8 +803,6 @@ static int notification2hv (pTHX_ notification_t *n, HV *hash) static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash) { - int i; - AV *values; AV *children; @@ -830,7 +819,7 @@ static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash) return -1; } - for (i = 0; i < ci->values_num; ++i) { + for (int i = 0; i < ci->values_num; ++i) { SV *value; switch (ci->values[i].type) { @@ -867,7 +856,7 @@ static int oconfig_item2hv (pTHX_ oconfig_item_t *ci, HV *hash) return -1; } - for (i = 0; i < ci->children_num; ++i) { + for (int i = 0; i < ci->children_num; ++i) { HV *child = newHV (); if (0 != oconfig_item2hv (aTHX_ ci->children + i, child)) { @@ -988,15 +977,13 @@ static int pplugin_write (pTHX_ const char *plugin, AV *data_set, HV *values) */ static int pplugin_dispatch_notification (pTHX_ HV *notif) { - notification_t n; + notification_t n = { 0 }; int ret; if (NULL == notif) return -1; - memset (&n, 0, sizeof (n)); - if (0 != hv2notification (aTHX_ notif, &n)) return -1; @@ -1178,7 +1165,7 @@ static int pplugin_call_all (pTHX_ int type, ...) } /* static int pplugin_call_all (int, ...) */ /* - * collectd's perl interpreter based thread implementation. + * collectd's Perl interpreter based thread implementation. * * This has been inspired by Perl's ithreads introduced in version 5.6.0. */ @@ -1251,7 +1238,7 @@ static c_ithread_t *c_ithread_create (PerlInterpreter *base) assert (NULL != perl_threads); - t = (c_ithread_t *)smalloc (sizeof (c_ithread_t)); + t = smalloc (sizeof (*t)); memset (t, 0, sizeof (c_ithread_t)); t->interp = (NULL == base) @@ -1464,7 +1451,7 @@ static int fc_create (int type, const oconfig_item_t *ci, void **user_data) return -1; } - data = (pfc_user_data_t *)smalloc (sizeof (*data)); + data = smalloc (sizeof (*data)); data->name = sstrdup (ci->values[0].value.string); data->user_data = newSV (0); @@ -2115,9 +2102,8 @@ static int perl_flush (cdtime_t timeout, const char *identifier, static int perl_shutdown (void) { - c_ithread_t *t = NULL; - - int ret = 0; + c_ithread_t *t; + int ret; dTHX; @@ -2127,8 +2113,6 @@ static int perl_shutdown (void) return 0; if (NULL == aTHX) { - t = NULL; - pthread_mutex_lock (&perl_threads->mutex); t = c_ithread_create (perl_threads->head->interp); pthread_mutex_unlock (&perl_threads->mutex); @@ -2161,20 +2145,15 @@ static int perl_shutdown (void) thr->shutdown = 1; if (thr->running) { - /* Give some time to thread to exit from pi */ - WARNING ("perl shutdown: thread is running inside perl. Waiting."); + /* Give some time to thread to exit from Perl interpreter */ + WARNING ("perl shutdown: Thread is running inside Perl. Waiting."); ts_wait.tv_sec = 0; ts_wait.tv_nsec = 500000; nanosleep (&ts_wait, NULL); } if (thr->running) { - /* This will crash collectd process later due to PERL_SYS_TERM() */ - //ERROR ("perl shutdown: thread hangs inside perl. " - // "Skipped perl interpreter destroy."); - //continue; - - ERROR ("perl shutdown: thread hangs inside perl. Thread killed."); pthread_kill (thr->pthread, SIGTERM); + ERROR ("perl shutdown: Thread hangs inside Perl. Thread killed."); } c_ithread_destroy (thr); } @@ -2253,21 +2232,19 @@ static void xs_init (pTHX) SV *tmp = NULL; char *file = __FILE__; - int i = 0; - dXSUB_SYS; /* enable usage of Perl modules using shared libraries */ newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); /* register API */ - for (i = 0; NULL != api[i].f; ++i) + for (int i = 0; NULL != api[i].f; ++i) newXS (api[i].name, api[i].f, file); stash = gv_stashpv ("Collectd", 1); /* export "constants" */ - for (i = 0; '\0' != constants[i].name[0]; ++i) + for (int i = 0; '\0' != constants[i].name[0]; ++i) newCONSTSUB (stash, constants[i].name, newSViv (constants[i].value)); /* export global variables @@ -2276,7 +2253,7 @@ static void xs_init (pTHX) * accessing any such variable (this is basically the same as using * tie() in Perl) */ /* global strings */ - for (i = 0; '\0' != g_strings[i].name[0]; ++i) { + for (int i = 0; '\0' != g_strings[i].name[0]; ++i) { tmp = get_sv (g_strings[i].name, 1); sv_magicext (tmp, NULL, PERL_MAGIC_ext, &g_pv_vtbl, g_strings[i].var, 0); @@ -2301,9 +2278,7 @@ static int init_pi (int argc, char **argv) log_info ("Initializing Perl interpreter..."); #if COLLECT_DEBUG { - int i = 0; - - for (i = 0; i < argc; ++i) + for (int i = 0; i < argc; ++i) log_debug ("argv[%i] = \"%s\"", i, argv[i]); } #endif /* COLLECT_DEBUG */ @@ -2322,7 +2297,7 @@ static int init_pi (int argc, char **argv) #endif PERL_SYS_INIT3 (&argc, &argv, &environ); - perl_threads = (c_ithread_list_t *)smalloc (sizeof (c_ithread_list_t)); + perl_threads = smalloc (sizeof (*perl_threads)); memset (perl_threads, 0, sizeof (c_ithread_list_t)); pthread_mutexattr_init(&perl_threads->mutexattr); @@ -2408,7 +2383,7 @@ static int perl_config_loadplugin (pTHX_ oconfig_item_t *ci) aTHX = perl_threads->head->interp; - log_debug ("perl_config: loading perl plugin \"%s\"", value); + log_debug ("perl_config: Loading Perl plugin \"%s\"", value); load_module (PERL_LOADMOD_NOIMPORT, newSVpv (module_name, strlen (module_name)), Nullsv); return 0; @@ -2454,7 +2429,7 @@ static int perl_config_enabledebugger (pTHX_ oconfig_item_t *ci) value = ci->values[0].value.string; - perl_argv = (char **)realloc (perl_argv, + perl_argv = realloc (perl_argv, (++perl_argc + 1) * sizeof (char *)); if (NULL == perl_argv) { @@ -2466,7 +2441,7 @@ static int perl_config_enabledebugger (pTHX_ oconfig_item_t *ci) perl_argv[perl_argc - 1] = "-d"; } else { - perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 4); + perl_argv[perl_argc - 1] = smalloc (strlen (value) + 4); sstrncpy (perl_argv[perl_argc - 1], "-d:", 4); sstrncpy (perl_argv[perl_argc - 1] + 3, value, strlen (value) + 1); } @@ -2491,7 +2466,7 @@ static int perl_config_includedir (pTHX_ oconfig_item_t *ci) value = ci->values[0].value.string; if (NULL == aTHX) { - perl_argv = (char **)realloc (perl_argv, + perl_argv = realloc (perl_argv, (++perl_argc + 1) * sizeof (char *)); if (NULL == perl_argv) { @@ -2499,7 +2474,7 @@ static int perl_config_includedir (pTHX_ oconfig_item_t *ci) exit (3); } - perl_argv[perl_argc - 1] = (char *)smalloc (strlen (value) + 3); + perl_argv[perl_argc - 1] = smalloc (strlen (value) + 3); sstrncpy(perl_argv[perl_argc - 1], "-I", 3); sstrncpy(perl_argv[perl_argc - 1] + 2, value, strlen (value) + 1); @@ -2572,11 +2547,10 @@ static int perl_config_plugin (pTHX_ oconfig_item_t *ci) static int perl_config (oconfig_item_t *ci) { int status = 0; - int i = 0; dTHXa (NULL); - for (i = 0; i < ci->children_num; ++i) { + for (int i = 0; i < ci->children_num; ++i) { oconfig_item_t *c = ci->children + i; int current_status = 0; @@ -2617,7 +2591,7 @@ static int perl_config (oconfig_item_t *ci) void module_register (void) { perl_argc = 4; - perl_argv = (char **)smalloc ((perl_argc + 1) * sizeof (char *)); + perl_argv = smalloc ((perl_argc + 1) * sizeof (*perl_argv)); /* default options for the Perl interpreter */ perl_argv[0] = "";