diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | example/example.cpp | 16 | ||||
-rw-r--r-- | example/example.hpp | 15 | ||||
-rw-r--r-- | utils.cpp | 33 |
4 files changed, 59 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac index efdd0b8..db3bc83 100644 --- a/configure.ac +++ b/configure.ac @@ -17,7 +17,7 @@ AX_CXX_COMPILE_STDCXX_17([noext]) AX_APPEND_COMPILE_FLAGS([-Wall -Werror], [CXXFLAGS]) # Checks for library functions. -LT_INIT([dlopen]) # Required for systemd linking +LT_INIT([dlopen disable-static shared]) # Required for systemd linking LT_LIB_DLLOAD # Checks for libraries. diff --git a/example/example.cpp b/example/example.cpp index 929e4d1..cc36e88 100644 --- a/example/example.cpp +++ b/example/example.cpp @@ -181,11 +181,17 @@ void setupExampleHandler() __attribute__((constructor)); void setupExampleHandler() { - auto* manager = getBlobManager(); - if (!manager->registerHandler(std::make_unique<ExampleBlobHandler>())) - { - log<level::ERR>("Failed to register Example Handler"); - } + // You don't need to do anything in the constructor. } } // namespace blobs + +/** + * This method is required by the blob manager. + * + * It is called to grab a handler for registering the blob handler instance. + */ +std::unique_ptr<blobs::GenericBlobInterface> createHandler() +{ + return std::make_unique<blobs::ExampleBlobHandler>(); +} diff --git a/example/example.hpp b/example/example.hpp index a85c275..335eade 100644 --- a/example/example.hpp +++ b/example/example.hpp @@ -1,10 +1,25 @@ #pragma once #include <blobs-ipmid/blobs.hpp> +#include <memory> #include <string> #include <unordered_map> #include <vector> +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This method must be declared as extern C for blob manager to lookup the + * symbol. + */ +std::unique_ptr<blobs::GenericBlobInterface> createHandler(); + +#ifdef __cplusplus +} +#endif + namespace blobs { @@ -2,7 +2,9 @@ #include <dlfcn.h> +#include <blobs-ipmid/manager.hpp> #include <experimental/filesystem> +#include <memory> #include <phosphor-logging/log.hpp> #include <regex> @@ -12,9 +14,13 @@ namespace blobs namespace fs = std::experimental::filesystem; using namespace phosphor::logging; +using HandlerFactory = std::unique_ptr<GenericBlobInterface> (*)(); + void loadLibraries(const std::string& path) { void* libHandle = NULL; + HandlerFactory factory; + auto* manager = getBlobManager(); for (const auto& p : fs::recursive_directory_iterator(path)) { @@ -30,12 +36,37 @@ void loadLibraries(const std::string& path) continue; } - libHandle = dlopen(ps.c_str(), RTLD_NOW); + libHandle = dlopen(ps.c_str(), RTLD_NOW | RTLD_GLOBAL); if (!libHandle) { log<level::ERR>("ERROR opening", entry("HANDLER=%s", ps.c_str()), entry("ERROR=%s", dlerror())); + continue; } + + dlerror(); /* Clear any previous error. */ + + factory = + reinterpret_cast<HandlerFactory>(dlsym(libHandle, "createHandler")); + + const char* error = dlerror(); + if (error) + { + log<level::ERR>("ERROR loading symbol", + entry("HANDLER=%s", ps.c_str()), + entry("ERROR=%s", error)); + continue; + } + + std::unique_ptr<GenericBlobInterface> result = factory(); + if (!result) + { + log<level::ERR>("Unable to create handler", + entry("HANDLER=%s", ps.c_str())); + continue; + } + + manager->registerHandler(std::move(result)); } } |