changeset 706:bd7feaa002cb

Irccd: check ABI compatibility in dynlib_plugin
author David Demelier <markand@malikania.fr>
date Fri, 06 Jul 2018 19:32:54 +0200
parents 4b5dba257d81
children 48afa8c41f50
files cmake/IrccdVersion.cmake cmake/internal/sysconfig.hpp.in libirccd/irccd/daemon/dynlib_plugin.cpp libirccd/irccd/daemon/dynlib_plugin.hpp plugins/links/links.cpp
diffstat 5 files changed, 48 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/IrccdVersion.cmake	Fri Jul 06 22:10:10 2018 +0200
+++ b/cmake/IrccdVersion.cmake	Fri Jul 06 19:32:54 2018 +0200
@@ -32,7 +32,7 @@
 set(IRCCD_VERSION_MINOR "0")
 set(IRCCD_VERSION_PATCH "0")
 set(IRCCD_VERSION "${IRCCD_VERSION_MAJOR}.${IRCCD_VERSION_MINOR}.${IRCCD_VERSION_PATCH}-dev${HG_REV}")
-set(IRCCD_VERSION_SHLIB "3")
+set(IRCCD_VERSION_SHLIB "1")
 
 #
 # Irccd release date.
--- a/cmake/internal/sysconfig.hpp.in	Fri Jul 06 22:10:10 2018 +0200
+++ b/cmake/internal/sysconfig.hpp.in	Fri Jul 06 19:32:54 2018 +0200
@@ -44,6 +44,7 @@
 #define IRCCD_VERSION_MAJOR     @IRCCD_VERSION_MAJOR@
 #define IRCCD_VERSION_MINOR     @IRCCD_VERSION_MINOR@
 #define IRCCD_VERSION_PATCH     @IRCCD_VERSION_PATCH@
+#define IRCCD_VERSION_SHLIB     @IRCCD_VERSION_SHLIB@
 #define IRCCD_VERSION           "@IRCCD_VERSION@"
 
 /*
--- a/libirccd/irccd/daemon/dynlib_plugin.cpp	Fri Jul 06 22:10:10 2018 +0200
+++ b/libirccd/irccd/daemon/dynlib_plugin.cpp	Fri Jul 06 19:32:54 2018 +0200
@@ -38,7 +38,7 @@
 
 namespace {
 
-std::string symbol(const std::string& path) noexcept
+auto symbol(const std::string& path) -> std::pair<std::string, std::string>
 {
     auto id = boost::filesystem::path(path).stem().string();
 
@@ -52,12 +52,10 @@
         return c == '-' ? '_' : c;
     });
 
-    return string_util::sprintf("irccd_plugin_%s", id);
-}
-
-std::shared_ptr<plugin> wrap(boost::shared_ptr<plugin> ptr) noexcept
-{
-    return std::shared_ptr<plugin>(ptr.get(), [ptr] (auto) mutable { ptr.reset(); });
+    return {
+        string_util::sprintf("irccd_abi_%s", id),
+        string_util::sprintf("irccd_init_%s", id)
+    };
 }
 
 } // !namespace
@@ -67,10 +65,32 @@
 {
 }
 
-std::shared_ptr<plugin> dynlib_plugin_loader::open(const std::string&,
-                                                   const std::string& path) noexcept
+auto dynlib_plugin_loader::open(const std::string& id,
+                                const std::string& path) -> std::shared_ptr<plugin>
 {
-    return wrap(boost::dll::import<plugin>(path, symbol(path)));
+    const auto [ abisym, initsym ] = symbol(path);
+
+    using abisym_func_type = unsigned ();
+    using initsym_func_type = std::unique_ptr<plugin> ();
+
+    const auto abi = boost::dll::import<abisym_func_type>(path, abisym);
+    const auto init = boost::dll::import<initsym_func_type>(path, initsym);
+
+    if (abi() != IRCCD_VERSION_SHLIB)
+        throw plugin_error(plugin_error::exec_error, id, "incompatible version");
+
+    auto plg = init();
+
+    if (!plg)
+        throw plugin_error(plugin_error::exec_error, id, "invalid plugin");
+
+    /*
+     * We need to keep a reference to `init' variable for the whole plugin
+     * lifetime.
+     */
+    return std::shared_ptr<plugin>(plg.release(), [init] (auto ptr) mutable {
+        delete ptr;
+    });
 }
 
 } // !irccd
--- a/libirccd/irccd/daemon/dynlib_plugin.hpp	Fri Jul 06 22:10:10 2018 +0200
+++ b/libirccd/irccd/daemon/dynlib_plugin.hpp	Fri Jul 06 19:32:54 2018 +0200
@@ -43,8 +43,8 @@
     /**
      * \copydoc plugin_loader::open
      */
-    std::shared_ptr<plugin> open(const std::string& id,
-                                 const std::string& file) noexcept override;
+    auto open(const std::string& id,
+              const std::string& file) -> std::shared_ptr<plugin> override;
 };
 
 } // !irccd
--- a/plugins/links/links.cpp	Fri Jul 06 22:10:10 2018 +0200
+++ b/plugins/links/links.cpp	Fri Jul 06 19:32:54 2018 +0200
@@ -424,8 +424,20 @@
 
 } // !namespace
 
-extern "C" BOOST_SYMBOL_EXPORT links_plugin irccd_plugin_links;
+extern "C" {
+
+BOOST_SYMBOL_EXPORT
+auto irccd_abi_links() -> unsigned
+{
+    return IRCCD_VERSION_SHLIB;
+}
 
-links_plugin irccd_plugin_links("links", "");
+BOOST_SYMBOL_EXPORT
+auto irccd_init_links() -> std::unique_ptr<plugin>
+{
+    return std::make_unique<links_plugin>("links", "");
+}
+
+} // !C
 
 } // !irccd