From 402f6df1e035c588f809eb4a85650c5ef3e4d082 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 20 May 2007 22:58:03 +0200 Subject: [PATCH] perl plugin: Unregister all callbacks from collectd when shutting down. If we do not unregister the callbacks there is still an entry point into the plugin after Perl has been shut down and its memory has been freed. This will cause segmentation faults if collectd tries to call any of the registered callbacks, e.g. by some plugin calling plugin_log () during shutdown. Important note: Unregistering the shutdown callback during shutdown is somewhat tricky. Doing that frees the llist_t entry in plugin.c:list_shutdown. This might cause a segfault in plugin_shutdown_all () when it tries to access the next pointer of that entry. If plugin_unregister_shutdown () is the last statement before the return from the shutdown callback this should be save in about 99% of all cases. Still there should be some better way to handle this. Signed-off-by: Sebastian Harl --- src/perl.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/perl.c b/src/perl.c index 3be37621..bcf7bb17 100644 --- a/src/perl.c +++ b/src/perl.c @@ -959,6 +959,8 @@ static XS (boot_Collectd) static int perl_config (const char *key, const char *value) { + assert (NULL != perl); + log_debug ("perl_config: key = \"%s\", value=\"%s\"", key, value); if (0 == strcasecmp (key, "LoadPlugin")) { @@ -993,24 +995,32 @@ static int perl_config (const char *key, const char *value) static int perl_init (void) { + assert (NULL != perl); + PERL_SET_CONTEXT (perl); return pplugin_call_all (PLUGIN_INIT); } /* static int perl_init (void) */ static int perl_read (void) { + assert (NULL != perl); + PERL_SET_CONTEXT (perl); return pplugin_call_all (PLUGIN_READ); } /* static int perl_read (void) */ static int perl_write (const data_set_t *ds, const value_list_t *vl) { + assert (NULL != perl); + PERL_SET_CONTEXT (perl); return pplugin_call_all (PLUGIN_WRITE, ds, vl); } /* static int perl_write (const data_set_t *, const value_list_t *) */ static void perl_log (int level, const char *msg) { + assert (NULL != perl); + PERL_SET_CONTEXT (perl); pplugin_call_all (PLUGIN_LOG, level, msg); return; @@ -1021,6 +1031,14 @@ static int perl_shutdown (void) int i = 0; int ret = 0; + plugin_unregister_log ("perl"); + plugin_unregister_config ("perl"); + plugin_unregister_init ("perl"); + plugin_unregister_read ("perl"); + plugin_unregister_write ("perl"); + + assert (NULL != perl); + PERL_SET_CONTEXT (perl); ret = pplugin_call_all (PLUGIN_SHUTDOWN); @@ -1054,8 +1072,11 @@ static int perl_shutdown (void) perl_destruct (perl); perl_free (perl); + perl = NULL; PERL_SYS_TERM (); + + plugin_unregister_shutdown ("perl"); return ret; } /* static void perl_shutdown (void) */ -- 2.11.0