]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[947-mt-compatibility-for-hooks] checkpoint
authorFrancis Dupont <fdupont@isc.org>
Tue, 22 Oct 2019 22:48:28 +0000 (00:48 +0200)
committerFrancis Dupont <fdupont@isc.org>
Tue, 5 Nov 2019 15:56:02 +0000 (16:56 +0100)
src/lib/hooks/hooks.h
src/lib/hooks/hooks_messages.cc
src/lib/hooks/hooks_messages.h
src/lib/hooks/hooks_messages.mes
src/lib/hooks/hooks_user.dox
src/lib/hooks/library_manager.cc
src/lib/hooks/library_manager.h
src/lib/hooks/pointer_converter.h
src/lib/hooks/tests/full_callout_library.cc
src/lib/hooks/tests/library_manager_unittest.cc
src/lib/hooks/tests/load_error_callout_library.cc

index 99c4547f881b128599937c4c300a60ab6395b30a..39b2e17b3bbde05c9823941832a7f188661016b7 100644 (file)
@@ -19,11 +19,14 @@ const int KEA_HOOKS_VERSION = 11;
 const char* const LOAD_FUNCTION_NAME = "load";
 const char* const UNLOAD_FUNCTION_NAME = "unload";
 const char* const VERSION_FUNCTION_NAME = "version";
+const char* const MULTI_THREADING_COMPATIBLE_FUNCTION_NAME =
+    "multi_threading_compatible";
 
 // Typedefs for pointers to the framework functions.
 typedef int (*version_function_ptr)();
 typedef int (*load_function_ptr)(isc::hooks::LibraryHandle&);
 typedef int (*unload_function_ptr)();
+typedef int (*multi_threading_compatible_function_ptr)();
 
 } // Anonymous namespace
 
index ca5d96214ab19bd3d8f2cf474c54ca0bc6874e34..4d003afa14f0b897d09c225ce6df498a39acc3c7 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../src/lib/hooks/hooks_messages.mes on Fri Feb 08 2019 20:16
+// File created from ../../../src/lib/hooks/hooks_messages.mes on Wed Oct 23 2019 00:13
 
 #include <cstddef>
 #include <log/message_types.h>
@@ -21,6 +21,8 @@ extern const isc::log::MessageID HOOKS_HOOK_LIST_RESET = "HOOKS_HOOK_LIST_RESET"
 extern const isc::log::MessageID HOOKS_INCORRECT_VERSION = "HOOKS_INCORRECT_VERSION";
 extern const isc::log::MessageID HOOKS_LIBRARY_LOADED = "HOOKS_LIBRARY_LOADED";
 extern const isc::log::MessageID HOOKS_LIBRARY_LOADING = "HOOKS_LIBRARY_LOADING";
+extern const isc::log::MessageID HOOKS_LIBRARY_MULTI_THREADING_COMPATIBLE = "HOOKS_LIBRARY_MULTI_THREADING_COMPATIBLE";
+extern const isc::log::MessageID HOOKS_LIBRARY_MULTI_THREADING_NOT_COMPATIBLE = "HOOKS_LIBRARY_MULTI_THREADING_NOT_COMPATIBLE";
 extern const isc::log::MessageID HOOKS_LIBRARY_UNLOADED = "HOOKS_LIBRARY_UNLOADED";
 extern const isc::log::MessageID HOOKS_LIBRARY_UNLOADING = "HOOKS_LIBRARY_UNLOADING";
 extern const isc::log::MessageID HOOKS_LIBRARY_VERSION = "HOOKS_LIBRARY_VERSION";
@@ -28,6 +30,7 @@ extern const isc::log::MessageID HOOKS_LOAD_ERROR = "HOOKS_LOAD_ERROR";
 extern const isc::log::MessageID HOOKS_LOAD_EXCEPTION = "HOOKS_LOAD_EXCEPTION";
 extern const isc::log::MessageID HOOKS_LOAD_FRAMEWORK_EXCEPTION = "HOOKS_LOAD_FRAMEWORK_EXCEPTION";
 extern const isc::log::MessageID HOOKS_LOAD_SUCCESS = "HOOKS_LOAD_SUCCESS";
+extern const isc::log::MessageID HOOKS_MULTI_THREADING_COMPATIBLE_EXCEPTION = "HOOKS_MULTI_THREADING_COMPATIBLE_EXCEPTION";
 extern const isc::log::MessageID HOOKS_NO_LOAD = "HOOKS_NO_LOAD";
 extern const isc::log::MessageID HOOKS_NO_UNLOAD = "HOOKS_NO_UNLOAD";
 extern const isc::log::MessageID HOOKS_NO_VERSION = "HOOKS_NO_VERSION";
@@ -59,6 +62,8 @@ const char* values[] = {
     "HOOKS_INCORRECT_VERSION", "hook library %1 is at version %2, require version %3",
     "HOOKS_LIBRARY_LOADED", "hooks library %1 successfully loaded",
     "HOOKS_LIBRARY_LOADING", "loading hooks library %1",
+    "HOOKS_LIBRARY_MULTI_THREADING_COMPATIBLE", "hooks library %1 reports its multi-threading compatibility as %2",
+    "HOOKS_LIBRARY_MULTI_THREADING_NOT_COMPATIBLE", "hooks library %1 is not compatible with multi-threading",
     "HOOKS_LIBRARY_UNLOADED", "hooks library %1 successfully unloaded",
     "HOOKS_LIBRARY_UNLOADING", "unloading library %1",
     "HOOKS_LIBRARY_VERSION", "hooks library %1 reports its version as %2",
@@ -66,6 +71,7 @@ const char* values[] = {
     "HOOKS_LOAD_EXCEPTION", "'load' function in hook library %1 threw an exception",
     "HOOKS_LOAD_FRAMEWORK_EXCEPTION", "'load' function in hook library %1 threw an exception: reason %2",
     "HOOKS_LOAD_SUCCESS", "'load' function in hook library %1 returned success",
+    "HOOKS_MULTI_THREADING_COMPATIBLE_EXCEPTION", "'multi_threading_compatible' function in hook library %1 threw an exception",
     "HOOKS_NO_LOAD", "no 'load' function found in hook library %1",
     "HOOKS_NO_UNLOAD", "no 'unload' function found in hook library %1",
     "HOOKS_NO_VERSION", "no 'version' function found in hook library %1",
index 288034665ee27a857bb65aac4fe21f71c6c6bb32..baf24659acdf717473928a06596325ce945fdc94 100644 (file)
@@ -1,4 +1,4 @@
-// File created from ../../../src/lib/hooks/hooks_messages.mes on Fri Feb 08 2019 20:16
+// File created from ../../../src/lib/hooks/hooks_messages.mes on Wed Oct 23 2019 00:13
 
 #ifndef HOOKS_MESSAGES_H
 #define HOOKS_MESSAGES_H
@@ -22,6 +22,8 @@ extern const isc::log::MessageID HOOKS_HOOK_LIST_RESET;
 extern const isc::log::MessageID HOOKS_INCORRECT_VERSION;
 extern const isc::log::MessageID HOOKS_LIBRARY_LOADED;
 extern const isc::log::MessageID HOOKS_LIBRARY_LOADING;
+extern const isc::log::MessageID HOOKS_LIBRARY_MULTI_THREADING_COMPATIBLE;
+extern const isc::log::MessageID HOOKS_LIBRARY_MULTI_THREADING_NOT_COMPATIBLE;
 extern const isc::log::MessageID HOOKS_LIBRARY_UNLOADED;
 extern const isc::log::MessageID HOOKS_LIBRARY_UNLOADING;
 extern const isc::log::MessageID HOOKS_LIBRARY_VERSION;
@@ -29,6 +31,7 @@ extern const isc::log::MessageID HOOKS_LOAD_ERROR;
 extern const isc::log::MessageID HOOKS_LOAD_EXCEPTION;
 extern const isc::log::MessageID HOOKS_LOAD_FRAMEWORK_EXCEPTION;
 extern const isc::log::MessageID HOOKS_LOAD_SUCCESS;
+extern const isc::log::MessageID HOOKS_MULTI_THREADING_COMPATIBLE_EXCEPTION;
 extern const isc::log::MessageID HOOKS_NO_LOAD;
 extern const isc::log::MessageID HOOKS_NO_UNLOAD;
 extern const isc::log::MessageID HOOKS_NO_VERSION;
index 41ec538085df37e01fad6702bb2dcac76b1f8b44..dbe318fee9e3fb1422d4597dfb2337b3c86962ad 100644 (file)
@@ -88,6 +88,17 @@ This is a debug message output just before the specified library is loaded.
 If the action is successfully, it will be followed by the
 HOOKS_LIBRARY_LOADED informational message.
 
+% HOOKS_LIBRARY_MULTI_THREADING_COMPATIBLE hooks library %1 reports its multi-threading compatibility as %2
+A debug message issued when the "multi_threading_compatible" function was
+called. The returned value (0 means not compatible, others compatible)
+is displayed.
+
+% HOOKS_LIBRARY_MULTI_THREADING_NOT_COMPATIBLE hooks library %1 is not compatible with multi-threading
+When multi-threading is enabled and the library is not compatible (either
+because the "multi_threading_compatible" function returned 0 or was not
+implemented) this error message is issued. The library must be removed
+from the configuration or the multi-threading disabled.
+
 % HOOKS_LIBRARY_UNLOADED hooks library %1 successfully unloaded
 This information message is issued when a user-supplied hooks library
 has been successfully unloaded.
@@ -125,6 +136,11 @@ installed.
 This is a debug message issued when the "load" function has been found
 in a hook library and has been successfully called.
 
+% HOOKS_MULTI_THREADING_COMPATIBLE_EXCEPTION 'multi_threading_compatible' function in hook library %1 threw an exception
+This error message is issued if the multi_threading_compatible()
+function in the specified hooks library was called and generated an
+exception.  The library is considered unusable and will not be loaded.
+
 % HOOKS_NO_LOAD no 'load' function found in hook library %1
 This is a debug message saying that the specified library was loaded
 but no function called "load" was found in it.  Providing the library
index 470be9249dad3146c7d26be08352bd110c0782f5..b9da7552be4285c4a1ece72b7864e24fe278fdb6 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -113,8 +113,10 @@ of three (user-supplied) functions:
 is built
 - load - called when the library is loaded by the server.
 - unload - called when the library is unloaded by the server.
+- multi_threading_compatible - defines the compatibility (or not) of
+the user-library and a multi-threaded DHCP service.
 
-Of these, only "version" is mandatory, although in our example, all three
+Of these, only "version" is mandatory, although in our example, all four
 are used.
 
 @subsubsection hooksdgVersionFunction The "version" Function
@@ -251,6 +253,40 @@ on an error.  The hooks framework will record a non-zero status return
 as an error in the current Kea log but otherwise ignore it.
 - As before, the function definitions are enclosed in 'extern "C"' braces.
 
+@subsubsection hooksdgMultiThreadingCompatibleFuntion The
+"multi_threading_compatible" function
+
+"multi_threading_compatible" is used by the hooks framework to check
+if the libraries it is loading are compatible with the DHCPv4 or DHCPv6
+erver multi-threading configuration. The value 0 means not compatible
+and is the default when the function is not implemented. not 0 values
+mean compatible.
+
+To be compatible means:
+- the code associated with DHCP packet processing callouts e.g.
+pkt4_receive or pkt6_send must be reentrant so the multi-threaded DHCP service
+can simultaneously calls more than once on of these callouts.
+- commands a library registers must be reentrant
+- when a library implements a backend API (e.g. host data source) the service
+methods must be reentrant
+- (shall be modified later) a library must not modify the internal
+configuration of the server, e.g. create or delete a subnet.
+
+In the tutoral, we'll put "multi_threading_compatible" in its own file,
+multi_threading_compatible.cc. The contents are:
+
+@code
+// multi_threading_compatible.cc
+
+extern "C" {
+
+int multi_threading_compatible() {
+    return (0);
+}
+
+}
+@endcode
+
 @subsection hooksdgCallouts Callouts
 
 Having sorted out the framework, we now come to the functions that
index ab10837da962cb77cea3f1dbce4c664e8c67cbe6..b7f719aaa28e578dfa0c096ed75d0efbf0d7343b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -7,6 +7,9 @@
 #include <config.h>
 
 #include <exceptions/exceptions.h>
+#if 0
+#include <util/multi_threading_mgr.h>
+#endif
 #include <hooks/hooks.h>
 #include <hooks/hooks_log.h>
 #include <hooks/callout_manager.h>
@@ -53,7 +56,7 @@ LibraryManager::LibraryManager(const std::string& name)
         : dl_handle_(NULL), index_(-1), manager_(), library_name_(name)
 {}
 
-// Destructor.  
+// Destructor.
 LibraryManager::~LibraryManager() {
     if (manager_) {
         // LibraryManager instantiated to load a library, so ensure that
@@ -134,6 +137,42 @@ LibraryManager::checkVersion() const {
     return (false);
 }
 
+// Check the multi-threading compatibility of the library
+
+bool
+LibraryManager::checkMultiThreadingCompatible() const {
+
+    // Compatible with single-threaded.
+#if 0
+    if (!MultiThreadingMgr::instance().getMode()) {
+        return (true);
+    }
+#endif
+
+    // Get the pointer to the "multi_threading_compatible" function.
+    PointerConverter pc(dlsym(dl_handle_, MULTI_THREADING_COMPATIBLE_FUNCTION_NAME));
+    int compatible = 0;
+    if (pc.multiThreadingCompatiblePtr()) {
+        try {
+            compatible = (*pc.multiThreadingCompatiblePtr())();
+        } catch (...) {
+            LOG_ERROR(hooks_logger, HOOKS_MULTI_THREADING_COMPATIBLE_EXCEPTION)
+                .arg(library_name_);
+            return (false);
+        }
+
+        LOG_DEBUG(hooks_logger, HOOKS_DBG_CALLS,
+                  HOOKS_LIBRARY_MULTI_THREADING_COMPATIBLE)
+            .arg(library_name_)
+            .arg(compatible);
+    }
+    if (compatible == 0) {
+        LOG_ERROR(hooks_logger, HOOKS_LIBRARY_MULTI_THREADING_NOT_COMPATIBLE)
+            .arg(library_name_);
+    }
+    return (compatible != 0);
+}
+
 // Register the standard callouts
 
 void
@@ -275,9 +314,12 @@ LibraryManager::loadLibrary() {
         isc::log::LoggerManager::logDuplicatedMessages();
 
         // Library opened OK, see if a version function is present and if so,
-        // check what value it returns.
+        // check what value it returns. Check multi-threading compatibility.
+#if 0
+        if (checkVersion() && checkMultiThreadingCompatible()) {
+#else
         if (checkVersion()) {
-
+#endif
             // Version OK, so now register the standard callouts and call the
             // library's load() function if present.
             registerStandardCallouts();
@@ -360,7 +402,12 @@ LibraryManager::validateLibrary(const std::string& name) {
     LibraryManager manager(name);
 
     // Try to open it and, if we succeed, check the version.
+#if 0
+    bool validated = manager.openLibrary() && manager.checkVersion() &&
+        checkMultiThreadingCompatible();
+#else
     bool validated = manager.openLibrary() && manager.checkVersion();
+#endif
 
     // Regardless of whether the version checked out, close the library. (This
     // is a no-op if the library failed to open.)
index 5f6bc4cac727fcee324ebef5005a2e50bc476dd6..14acf8a64dd3986c356a444279b7eb3855e0678a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -99,7 +99,7 @@ public:
     ///
     /// A static method that is used to validate a library.  Validation checks
     /// that the library can be opened, that "version" exists, and that it
-    /// returns the right number.
+    /// returns the right number, and the multi-threading compatibility.
     ///
     /// @param name Name of the library to validate
     ///
@@ -109,15 +109,17 @@ public:
 
     /// @brief Loads a library
     ///
-    /// Open the library and check the version.  If all is OK, load all standard
-    /// symbols then call "load" if present.
+    /// Open the library, check the version and the multi-threading
+    /// compatibility.  If all is OK, load all standard symbols then
+    /// call "load" if present.
     ///
-    /// It also calls the @c isc::log::MessageInitializer::loadDictionary, prior
-    /// to invoking the @c version function of the library, to update the global
-    /// logging dictionary with the log messages registered by the loaded library.
+    /// It also calls the @c isc::log::MessageInitializer::loadDictionary,
+    /// prior to invoking the @c version function of the library, to
+    /// update the global logging dictionary with the log messages
+    /// registered by the loaded library.
     ///
-    /// @return true if the library loaded successfully, false otherwise. In the
-    ///         latter case, the library will be unloaded if possible.
+    /// @return true if the library loaded successfully, false otherwise.
+    /// In the latter case, the library will be unloaded if possible.
     bool loadLibrary();
 
     /// @brief Unloads a library
@@ -176,6 +178,16 @@ protected:
     /// @return bool true if the check succeeded
     bool checkVersion() const;
 
+    /// @brief Check multi-threading compatibility
+    ///
+    /// If the multi-threading mode is false returns true, else with
+    /// the library open, accesses the "multi_threading_compatible()"
+    /// function and returns false if not exists or has value 0, returns
+    /// true otherwise.
+    ///
+    /// @return bool true if the check succeeded
+    bool checkMultiThreadingCompatible() const;
+
     /// @brief Register standard callouts
     ///
     /// Loops through the list of hook names and searches the library for
index d160affd557749c779ce9ee16adedce4e6c80d4f..56eb7e2f2efb946d6ec220d73c84157dc1788461 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -92,6 +92,13 @@ public:
         return (pointers_.version_ptr);
     }
 
+    /// @brief Return pointer to multi_threading_compatible function
+    ///
+    /// @return Pointer to the multi_threading_compatible function
+    multi_threading_compatible_function_ptr multiThreadingCompatiblePtr() const {
+        return (pointers_.multi_threading_compatible_ptr);
+    }
+
     ///@}
 
 private:
@@ -103,6 +110,8 @@ private:
         load_function_ptr       load_ptr;       // Pointer to load function
         unload_function_ptr     unload_ptr;     // Pointer to unload function
         version_function_ptr    version_ptr;    // Pointer to version function
+        multi_threading_compatible_function_ptr multi_threading_compatible_ptr;
+        // Pointer to multi_threading_compatible function
     } pointers_;
 };
 
index 35bc2f7e8876ed5bcfe06ebffee9904cadfc545a..8d3784d70856ba78b2e42f7fbd677eab8502ff78 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 ///
 /// The characteristics of this library are:
 ///
-/// - All three framework functions are supplied (version(), load() and
-///   unload()), with unload() creating a marker file.  The test code checks
-///   for the presence of this file, so verifying that unload() has been run.
+/// - All four framework functions are supplied (version(), load(),
+///   unload() and multi_threading_compatible()), with unload()
+///   creating a marker file.  The test code checks for the presence
+///   of this file, so verifying that unload() has been run.
 ///
 /// - One standard and two non-standard callouts are supplied, with the latter
 ///   being registered by the load() function.
@@ -167,5 +168,10 @@ unload() {
     return (0);
 }
 
+int
+multi_threading_compatible() {
+    return (1);
+}
+
 };
 
index 07202b26d49bed780bd198960ac77ae48cf4c6b4..d10b447582a418c95104266eecddc7bbbcaa3941 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 #include <log/message_dictionary.h>
 #include <log/message_initializer.h>
 
+#if 0
+#include <util/multi_threading_mgr.h>
+#endif
+
 #include <gtest/gtest.h>
 
 #include <algorithm>
@@ -135,6 +139,7 @@ public:
     using LibraryManager::openLibrary;
     using LibraryManager::closeLibrary;
     using LibraryManager::checkVersion;
+    using LibraryManager::checkMultiThreadingCompatible;
     using LibraryManager::registerStandardCallouts;
     using LibraryManager::runLoad;
     using LibraryManager::runUnload;
@@ -236,6 +241,96 @@ TEST_F(LibraryManagerTest, CorrectVersionReturned) {
     EXPECT_TRUE(lib_manager.closeLibrary());
 }
 
+// Checks that the code handles the case of a library with no
+// multi_threading_compatible function.
+
+TEST_F(LibraryManagerTest, NoMultiThreadingCompatible) {
+    PublicLibraryManager lib_manager(std::string(BASIC_CALLOUT_LIBRARY),
+                                     0, callout_manager_);
+
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+#if 0
+    // Not multi-threading compatible: does not matter without MT.
+    EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+
+    // Not multi-threading compatible: does matter with MT.
+    //// set MT
+    EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+#endif
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Checks that the code handles the case of a library with a
+// multi_threading_compatible function returning 0 (not compatible).
+
+TEST_F(LibraryManagerTest, multiThreadingNotCompatible) {
+    PublicLibraryManager lib_manager(std::string(LOAD_ERROR_CALLOUT_LIBRARY),
+                                     0, callout_manager_);
+
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+#if 0
+    // Not multi-threading compatible: does not matter without MT.
+    EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+
+    // Not multi-threading compatible: does matter with MT.
+    //// set MT
+    EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+#endif
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Checks that the code handles the case of a library with a
+// multi_threading_compatible function returning 1 (compatible)
+
+TEST_F(LibraryManagerTest, multiThreadingCompatible) {
+    PublicLibraryManager lib_manager(std::string(FULL_CALLOUT_LIBRARY),
+                                     0, callout_manager_);
+
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+    // Multi-threading compatible: does not matter without MT.
+    EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+
+    // Multi-threading compatible: does matter with MT.
+    //// set MT
+    EXPECT_TRUE(lib_manager.checkMultiThreadingCompatible());
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
+// Checks that the code handles the case of a library with a
+// multi_threading_compatible function returning 1 (compatible)
+
+TEST_F(LibraryManagerTest, multiThreadingCompatibleException) {
+    PublicLibraryManager lib_manager(std::string(FRAMEWORK_EXCEPTION_LIBRARY),
+                                     0, callout_manager_);
+
+    // Open should succeed.
+    EXPECT_TRUE(lib_manager.openLibrary());
+
+#if 0
+    // Throw exception: does not matter without MT.
+    EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+#endif
+
+    // Throw exception: does matter with MT.
+    //// set MT
+    EXPECT_FALSE(lib_manager.checkMultiThreadingCompatible());
+
+    // Tidy up.
+    EXPECT_TRUE(lib_manager.closeLibrary());
+}
+
 // Checks the registration of standard callouts.
 
 TEST_F(LibraryManagerTest, RegisterStandardCallouts) {
index 87bcd6c1fad7ac5e9b5f2fea7141d0011d9729d2..26f0d9e2b6a549920d0aec60e9833d7a9bc9e731 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2013-2015 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 Internet Systems Consortium, Inc. ("ISC")
 //
 // This Source Code Form is subject to the terms of the Mozilla Public
 // License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -38,5 +38,10 @@ unload() {
     return (1);
 }
 
+int
+multi_threading_compatible() {
+    return (0);
+}
+
 };