Make sure that all features of critical plugins are loaded

This commit is contained in:
Tobias Brunner
2012-06-25 17:03:07 +02:00
parent bc6d944705
commit e07122436c
+64 -5
View File
@@ -68,6 +68,11 @@ struct plugin_entry_t {
*/ */
plugin_t *plugin; plugin_t *plugin;
/**
* TRUE, if the plugin is marked as critical
*/
bool critical;
/** /**
* dlopen handle, if in separate lib * dlopen handle, if in separate lib
*/ */
@@ -113,7 +118,8 @@ static bool plugin_feature_equals(plugin_feature_t *a, plugin_feature_t *b)
* FAILED, if the plugin could not be constructed * FAILED, if the plugin could not be constructed
*/ */
static status_t create_plugin(private_plugin_loader_t *this, void *handle, static status_t create_plugin(private_plugin_loader_t *this, void *handle,
char *name, bool integrity, plugin_entry_t **entry) char *name, bool integrity, bool critical,
plugin_entry_t **entry)
{ {
char create[128]; char create[128];
plugin_t *plugin; plugin_t *plugin;
@@ -149,6 +155,7 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
} }
INIT(*entry, INIT(*entry,
.plugin = plugin, .plugin = plugin,
.critical = critical,
.loaded = linked_list_create(), .loaded = linked_list_create(),
.failed = linked_list_create(), .failed = linked_list_create(),
); );
@@ -159,12 +166,13 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
/** /**
* load a single plugin * load a single plugin
*/ */
static bool load_plugin(private_plugin_loader_t *this, char *name, char *file) static bool load_plugin(private_plugin_loader_t *this, char *name, char *file,
bool critical)
{ {
plugin_entry_t *entry; plugin_entry_t *entry;
void *handle; void *handle;
switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, &entry)) switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, critical, &entry))
{ {
case SUCCESS: case SUCCESS:
this->plugins->insert_last(this->plugins, entry); this->plugins->insert_last(this->plugins, entry);
@@ -190,7 +198,7 @@ static bool load_plugin(private_plugin_loader_t *this, char *name, char *file)
DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror()); DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror());
return FALSE; return FALSE;
} }
if (create_plugin(this, handle, name, TRUE, &entry) != SUCCESS) if (create_plugin(this, handle, name, TRUE, critical, &entry) != SUCCESS)
{ {
dlclose(handle); dlclose(handle);
return FALSE; return FALSE;
@@ -473,6 +481,55 @@ static int unload_features(private_plugin_loader_t *this, plugin_entry_t *entry)
return unloaded; return unloaded;
} }
/**
* Check that we have all features loaded for critical plugins
*/
static bool missing_critical_features(private_plugin_loader_t *this)
{
enumerator_t *enumerator;
plugin_entry_t *entry;
bool critical_failed = FALSE;
enumerator = this->plugins->create_enumerator(this->plugins);
while (enumerator->enumerate(enumerator, &entry))
{
if (!entry->plugin->get_features)
{ /* feature interface not supported */
continue;
}
if (entry->critical)
{
plugin_feature_t *feature;
char *name, *provide;
int count, i, failed = 0;
name = entry->plugin->get_name(entry->plugin);
count = entry->plugin->get_features(entry->plugin, &feature);
for (i = 0; i < count; i++, feature++)
{
if (feature->kind == FEATURE_PROVIDE &&
!feature_loaded(this, entry, feature))
{
provide = plugin_feature_get_string(feature);
DBG2(DBG_LIB, " failed to load %s in critical plugin '%s'",
provide, name);
free(provide);
failed++;
}
}
if (failed)
{
DBG1(DBG_LIB, "failed to load %d feature%s in critical plugin "
"'%s'", failed, failed > 1 ? "s" : "", name);
critical_failed = TRUE;
}
}
}
enumerator->destroy(enumerator);
return critical_failed;
}
/** /**
* Remove plugins that we were not able to load any features from. * Remove plugins that we were not able to load any features from.
*/ */
@@ -533,7 +590,7 @@ METHOD(plugin_loader_t, load_plugins, bool,
{ {
return FALSE; return FALSE;
} }
if (!load_plugin(this, token, file) && critical) if (!load_plugin(this, token, file, critical) && critical)
{ {
critical_failed = TRUE; critical_failed = TRUE;
DBG1(DBG_LIB, "loading critical plugin '%s' failed", token); DBG1(DBG_LIB, "loading critical plugin '%s' failed", token);
@@ -556,6 +613,8 @@ METHOD(plugin_loader_t, load_plugins, bool,
} }
/* report missing dependencies */ /* report missing dependencies */
load_features(this, FALSE, TRUE); load_features(this, FALSE, TRUE);
/* check for unloaded features provided by critical plugins */
critical_failed = missing_critical_features(this);
/* unload plugins that we were not able to load any features for */ /* unload plugins that we were not able to load any features for */
purge_plugins(this); purge_plugins(this);
} }