Fix dlopened objects management 84/28884/8
authorZofia Abramowska <z.abramowska@samsung.com>
Thu, 16 Oct 2014 16:35:48 +0000 (18:35 +0200)
committerZofia Abramowska <z.abramowska@samsung.com>
Fri, 14 Nov 2014 18:23:41 +0000 (19:23 +0100)
* Add destroy function type, so deletion is compatible with allocation
* Remove extern "C" from plugin creation/destruction typedefs
* Add proper comments, so expected names of creation/destruction
function symbol are known to API user

Change-Id: I019f5bf83afc94945c8efc62e99dd324c419cc33

src/include/cynara-plugin.h
src/service/plugin/PluginManager.cpp
src/service/plugin/PluginManager.h

index 83956fe..a9d6da7 100644 (file)
@@ -34,11 +34,20 @@ namespace Cynara {
 
 class ExternalPluginInterface;
 
-extern "C" {
-typedef ExternalPluginInterface *(*createPlugin)(void);
-}
+/**
+ * Type of function used for creating objects implementing ExternalPluginInterface.
+ * Inside plugin library function with create_t signature should have symbol
+ * named "create".
+ */
+typedef ExternalPluginInterface *(*create_t)(void);
+/**
+ * Type of function used for destroying objects created with "create".
+ * Inside plugin library function with destroy_t signature should have symbol
+ * named "destroy".
+ */
+typedef void (*destroy_t)(ExternalPluginInterface *);
 
-//These typedefs will be defined in external headers
+// These typedefs will be defined in external headers
 typedef std::string PluginData;
 typedef std::string AgentType;
 typedef std::vector<PolicyType> PolicyTypes;
index 3d21b49..c591805 100644 (file)
@@ -53,6 +53,14 @@ PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) {
     loadPlugins();
 }
 
+PluginManager::~PluginManager(void) {
+    // We have to be sure, that external objects will be destroyed
+    // before handles to libraries are closed.
+    for (auto &plugin : m_plugins) {
+        plugin.second.reset();
+    }
+}
+
 ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) {
     return m_plugins[pType];
 }
@@ -90,7 +98,7 @@ void PluginManager::openPlugin(const std::string &path) {
 
     //Flush any previous errors
     dlerror();
-    createPlugin func = reinterpret_cast<createPlugin>(dlsym(handle, "create"));
+    create_t creator = reinterpret_cast<create_t>(dlsym(handle, "create"));
 
     char *error;
     if ((error = dlerror()) != NULL) {
@@ -98,7 +106,13 @@ void PluginManager::openPlugin(const std::string &path) {
         return;
     }
 
-    ExternalPluginPtr pluginPtr(func());
+    destroy_t destroyer = reinterpret_cast<destroy_t>(dlsym(handle, "destroy"));
+    if ((error = dlerror()) != NULL) {
+        LOGE("Couldn't resolve symbol <destroy> from lib <%s> : <%s>", path.c_str(), error);
+        return;
+    }
+
+    ExternalPluginPtr pluginPtr(creator(), destroyer);
 
     if (!pluginPtr) {
         LOGE("Couldn't create plugin for <%s>", path.c_str());
index 6338cad..1abc6e6 100644 (file)
@@ -23,6 +23,7 @@
 #ifndef SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_
 #define SRC_SERVICE_PLUGIN_PLUGINMANAGER_H_
 
+#include <functional>
 #include <list>
 #include <map>
 #include <memory>
@@ -37,7 +38,7 @@ class PluginManager {
 public:
     PluginManager(const std::string &pluginDir);
     ExternalPluginPtr getPlugin(PolicyType pType);
-    ~PluginManager() {}
+    ~PluginManager();
 
 private:
     typedef std::unique_ptr<void, std::function<void (void*)>> PluginLibPtr;