Skip to content

Commit

Permalink
Represent plugins explicitly
Browse files Browse the repository at this point in the history
  • Loading branch information
nathanwbrei committed Aug 9, 2024
1 parent 74a7900 commit f027a03
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 28 deletions.
47 changes: 24 additions & 23 deletions src/libraries/JANA/Services/JPluginLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <unistd.h>
#include <set>
#include <filesystem>
#include <memory>

class JApplication;

Expand Down Expand Up @@ -163,7 +164,7 @@ void JPluginLoader::attach_plugins(JComponentManager* jcm) {
LOG_DEBUG(m_logger) << "Found!" << LOG_END;
try {
jcm->next_plugin(plugin_shortname);
attach_plugin(fullpath.c_str());
attach_plugin(plugin_shortname, fullpath);
paths_checked << "Loaded successfully" << std::endl;
found_plugin = true;
break;
Expand Down Expand Up @@ -213,7 +214,7 @@ void JPluginLoader::attach_plugins(JComponentManager* jcm) {
}


void JPluginLoader::attach_plugin(std::string soname) {
void JPluginLoader::attach_plugin(std::string name, std::string path) {

/// Attach a plugin by opening the shared object file and running the
/// InitPlugin_t(JApplication* app) global C-style routine in it.
Expand All @@ -230,46 +231,46 @@ void JPluginLoader::attach_plugin(std::string soname) {
///

// Open shared object
void* handle = dlopen(soname.c_str(), RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE);
void* handle = dlopen(path.c_str(), RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE);
if (!handle) {
std::string err = dlerror();
LOG_DEBUG(m_logger) << "Plugin dlopen() failed: " << err << LOG_END;
LOG_ERROR(m_logger) << "Plugin dlopen() failed: " << err << LOG_END;
throw JException("Plugin dlopen() failed: %s", err.c_str());
}

// Look for an InitPlugin symbol
typedef void InitPlugin_t(JApplication* app);
InitPlugin_t* initialize_proc = (InitPlugin_t*) dlsym(handle, "InitPlugin");
if (initialize_proc) {
LOG_INFO(m_logger) << "Initializing plugin \"" << soname << "\"" << LOG_END;
LOG_INFO(m_logger) << "Initializing plugin \"" << name << "\" at path \"" << path << "\"" << LOG_END;
(*initialize_proc)(GetApplication());
m_sohandles[soname] = handle;
auto plugin = std::make_unique<JPlugin>(name, path);
plugin->m_app = GetApplication();
plugin->m_logger = m_logger;
plugin->m_handle = handle;
m_plugin_index[name] = plugin.get();
m_plugins.push_front(std::move(plugin));
// We push to the front so that plugins get unloaded in the reverse order they were originally added
} else {
dlclose(handle);
LOG_DEBUG(m_logger) << "Plugin \"" << soname
LOG_ERROR(m_logger) << "Plugin \"" << name
<< "\" does not have an InitPlugin() function. Ignoring." << LOG_END;
}
}


JPluginLoader::JPluginLoader() {}
JPlugin::~JPlugin() {

JPluginLoader::~JPluginLoader() {

// Loop over open plugin handles.
// Call FinalizePlugin if it has one and close it in all cases.
// Call FinalizePlugin()
typedef void FinalizePlugin_t(JApplication* app);
for( auto p :m_sohandles ){
auto soname = p.first;
auto handle = p.second;
FinalizePlugin_t* finalize_proc = (FinalizePlugin_t*) dlsym(handle, "FinalizePlugin");
if (finalize_proc) {
LOG_INFO(m_logger) << "Finalizing plugin \"" << soname << "\"" << LOG_END;
(*finalize_proc)(GetApplication());
}

// Close plugin handle
dlclose(handle);
FinalizePlugin_t* finalize_proc = (FinalizePlugin_t*) dlsym(m_handle, "FinalizePlugin");
if (finalize_proc) {
LOG_INFO(m_logger) << "Finalizing plugin \"" << m_name << "\"" << LOG_END;
(*finalize_proc)(m_app);
}

// Close plugin handle
dlclose(m_handle);
LOG_DEBUG(m_logger) << "Unloaded plugin \"" << m_name << "\"" << LOG_END;
}

28 changes: 23 additions & 5 deletions src/libraries/JANA/Services/JPluginLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,38 @@

#include <string>
#include <vector>
#include <list>


class JComponentManager;
class JApplication;

class JPlugin {
friend class JPluginLoader;
JApplication* m_app;
JLogger m_logger;
std::string m_name;
std::string m_path;
void* m_handle;
public:
JPlugin(std::string name, std::string path) : m_name(name), m_path(path) {};
~JPlugin();
std::string GetName() { return m_name; }
std::string GetPath() { return m_path; }
};

class JPluginLoader : public JService {

public:

JPluginLoader();
~JPluginLoader() override;
JPluginLoader() = default;
~JPluginLoader() override = default;
void Init() override;

void add_plugin(std::string plugin_name);
void add_plugin_path(std::string path);
void attach_plugins(JComponentManager* jcm);
void attach_plugin(std::string plugin_name);
void attach_plugin(std::string name, std::string path);
void resolve_plugin_paths();

private:
Expand All @@ -37,10 +52,13 @@ class JPluginLoader : public JService {
std::vector<std::string> m_plugins_to_exclude;
std::vector<std::string> m_plugin_paths;
std::string m_plugin_paths_str;
std::map<std::string, void*> m_sohandles; // key=plugin name val=dlopen handle

bool m_verbose = false;
// We wish to preserve each plugin's insertion order
// This way, plugins are unloaded in the reverse order they were added
std::list<std::unique_ptr<JPlugin>> m_plugins;
std::map<std::string, JPlugin*> m_plugin_index;

bool m_verbose = false;
};


Expand Down

0 comments on commit f027a03

Please sign in to comment.