/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
-
- The main author of Bacula is Kern Sibbald, with contributions from
- many others, a complete list can be found in the file AUTHORS.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version three of the GNU Affero General Public
- License as published by the Free Software Foundation, which is
- listed in the file LICENSE.
-
- 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.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of Kern Sibbald.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2016 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
*/
/*
* Plugin load/unloader for all Bacula daemons
static const int dbglvl = 50;
-/* All loaded plugins */
-alist *plugin_list = NULL;
+/*
+ * List of all loaded plugins.
+ *
+ * NOTE!!! This is a global do not try walking it with
+ * foreach_alist, you must use foreach_alist_index !!!!!!
+ */
+alist *b_plugin_list = NULL;
/*
* Create a new plugin "class" entry and enter it in the
* list of plugins. Note, this is not the same as
- * an instance of the plugin.
+ * an instance of the plugin.
*/
Plugin *new_plugin()
{
/*
* Load all the plugins in the specified directory.
*/
-bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
+bool load_plugins(void *binfo, void *bfuncs, const char *plugin_dir,
const char *type, bool is_plugin_compatible(Plugin *plugin))
{
bool found = false;
int len, type_len;
+ Dmsg0(dbglvl, "load_plugins\n");
name_max = pathconf(".", _PC_NAME_MAX);
if (name_max < 1024) {
name_max = 1024;
if (!(dp = opendir(plugin_dir))) {
berrno be;
- Jmsg(NULL, M_ERROR_TERM, 0, _("Failed to open Plugin directory %s: ERR=%s\n"),
+ Jmsg(NULL, M_ERROR_TERM, 0, _("Failed to open Plugin directory %s: ERR=%s\n"),
plugin_dir, be.bstrerror());
- Dmsg2(dbglvl, "Failed to open Plugin directory %s: ERR=%s\n",
+ Dmsg2(dbglvl, "Failed to open Plugin directory %s: ERR=%s\n",
plugin_dir, be.bstrerror());
goto get_out;
}
-
+
len = strlen(plugin_dir);
if (len > 0) {
need_slash = !IsPathSeparator(plugin_dir[len - 1]);
if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
if (!found) {
- Jmsg(NULL, M_WARNING, 0, _("Failed to find any plugins in %s\n"),
+ Jmsg(NULL, M_WARNING, 0, _("Failed to find any plugins in %s\n"),
plugin_dir);
Dmsg1(dbglvl, "Failed to find any plugins in %s\n", plugin_dir);
}
break;
}
- if (strcmp(result->d_name, ".") == 0 ||
+ if (strcmp(result->d_name, ".") == 0 ||
strcmp(result->d_name, "..") == 0) {
continue;
}
Dmsg3(dbglvl, "Rejected plugin: want=%s name=%s len=%d\n", type, result->d_name, len);
continue;
}
- Dmsg2(dbglvl, "Loaded plugin: name=%s len=%d\n", result->d_name, len);
-
+ Dmsg2(dbglvl, "Found plugin: name=%s len=%d\n", result->d_name, len);
+
pm_strcpy(fname, plugin_dir);
if (need_slash) {
pm_strcat(fname, "/");
plugin->file_len = strstr(plugin->file, type) - plugin->file;
plugin->pHandle = dlopen(fname.c_str(), RTLD_NOW);
if (!plugin->pHandle) {
- Jmsg(NULL, M_ERROR, 0, _("Plugin load %s failed: ERR=%s\n"),
- fname.c_str(), NPRT(dlerror()));
- Dmsg2(dbglvl, "Plugin load %s failed: ERR=%s\n", fname.c_str(),
- NPRT(dlerror()));
+ const char *error = dlerror();
+ Jmsg(NULL, M_ERROR, 0, _("dlopen plugin %s failed: ERR=%s\n"),
+ fname.c_str(), NPRT(error));
+ Dmsg2(dbglvl, "dlopen plugin %s failed: ERR=%s\n", fname.c_str(),
+ NPRT(error));
close_plugin(plugin);
continue;
}
if (!loadPlugin) {
Jmsg(NULL, M_ERROR, 0, _("Lookup of loadPlugin in plugin %s failed: ERR=%s\n"),
fname.c_str(), NPRT(dlerror()));
- Dmsg2(dbglvl, "Lookup of loadPlugin in plugin %s failed: ERR=%s\n",
+ Dmsg2(dbglvl, "Lookup of loadPlugin in plugin %s failed: ERR=%s\n",
fname.c_str(), NPRT(dlerror()));
close_plugin(plugin);
continue;
continue;
}
if (!is_plugin_compatible) {
- Dmsg0(50, "Plugin compatibility pointer not set.\n");
+ Dmsg0(50, "Plugin compatibility pointer not set.\n");
} else if (!is_plugin_compatible(plugin)) {
close_plugin(plugin);
continue;
}
found = true; /* found a plugin */
- plugin_list->append(plugin);
+ b_plugin_list->append(plugin);
}
get_out:
}
/*
- * Unload all the loaded plugins
+ * Unload all the loaded plugins
*/
void unload_plugins()
{
Plugin *plugin;
- if (!plugin_list) {
+ if (!b_plugin_list) {
return;
}
- foreach_alist(plugin, plugin_list) {
+ foreach_alist(plugin, b_plugin_list) {
/* Shut it down and unload it */
plugin->unloadPlugin();
+ /* TODO:
+ * If you get a SIGSEGV when using plugins then it is very plausible that
+ * one of the plugins has a memory leakage which cannot be tracked by
+ * SMARTALLOC mechanism when you need to disable dlclose() below for
+ * further investigation.
+ * The problem was registered as #0002330 (http://bugs.bacula.org/view.php?id=2330)
+ */
dlclose(plugin->pHandle);
if (plugin->file) {
free(plugin->file);
}
free(plugin);
}
- delete plugin_list;
- plugin_list = NULL;
+ delete b_plugin_list;
+ b_plugin_list = NULL;
}
/*
void dbg_print_plugin(FILE *fp)
{
Plugin *plugin;
- fprintf(fp, "Attempt to dump plugins. Hook count=%d\n", dbg_plugin_hook_count);
+ fprintf(fp, "List plugins. Hook count=%d\n", dbg_plugin_hook_count);
- if (!plugin_list) {
+ if (!b_plugin_list) {
return;
}
- foreach_alist(plugin, plugin_list) {
+ foreach_alist(plugin, b_plugin_list) {
for(int i=0; i < dbg_plugin_hook_count; i++) {
// dbg_plugin_hook_t *fct = dbg_plugin_hooks[i];
fprintf(fp, "Plugin %p name=\"%s\" disabled=%d\n",