From: Francis Dupont Date: Thu, 25 Jun 2020 13:29:33 +0000 (+0200) Subject: [#1282] Checkpoint: todo HA new test X-Git-Tag: Kea-1.7.10~132 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c2dbcd065c034cc4394fc19b6041aaf96300a76;p=thirdparty%2Fkea.git [#1282] Checkpoint: todo HA new test --- diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc index e18487723e..fa4096f00f 100644 --- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc +++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc @@ -232,14 +232,21 @@ ControlledDhcpv4Srv::commandLibReloadHandler(const string&, ConstElementPtr) { // stop thread pool (if running) MultiThreadingCriticalSection cs; - /// @todo delete any stored CalloutHandles referring to the old libraries - /// Get list of currently loaded libraries and reload them. - HookLibsCollection loaded = HooksManager::getLibraryInfo(); - bool status = HooksManager::loadLibraries(loaded); - if (!status) { + // Clear the packet queue. + MultiThreadingMgr::instance().getThreadPool().reset(); + + try { + /// Get list of currently loaded libraries and reload them. + HookLibsCollection loaded = HooksManager::getLibraryInfo(); + HooksManager::prepareUnloadLibraries(); + static_cast(HooksManager::unloadLibraries()); + bool status = HooksManager::loadLibraries(loaded); + if (!status) { + isc_throw(Unexpected, "Failed to reload hooks libraries."); + } + } catch (const std::exception& ex) { LOG_ERROR(dhcp4_logger, DHCP4_HOOKS_LIBS_RELOAD_FAIL); - ConstElementPtr answer = isc::config::createAnswer(1, - "Failed to reload hooks libraries."); + ConstElementPtr answer = isc::config::createAnswer(1, ex.what()); return (answer); } ConstElementPtr answer = isc::config::createAnswer(0, diff --git a/src/bin/dhcp4/dhcp4_messages.cc b/src/bin/dhcp4/dhcp4_messages.cc index 64395acbde..c2ae32a7bf 100644 --- a/src/bin/dhcp4/dhcp4_messages.cc +++ b/src/bin/dhcp4/dhcp4_messages.cc @@ -1,4 +1,4 @@ -// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Mon Jun 22 2020 17:28 +// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Thu Jun 25 2020 13:36 #include #include @@ -141,6 +141,7 @@ extern const isc::log::MessageID DHCP4_SHUTDOWN_REQUEST = "DHCP4_SHUTDOWN_REQUES extern const isc::log::MessageID DHCP4_SRV_CONSTRUCT_ERROR = "DHCP4_SRV_CONSTRUCT_ERROR"; extern const isc::log::MessageID DHCP4_SRV_D2STOP_ERROR = "DHCP4_SRV_D2STOP_ERROR"; extern const isc::log::MessageID DHCP4_SRV_DHCP4O6_ERROR = "DHCP4_SRV_DHCP4O6_ERROR"; +extern const isc::log::MessageID DHCP4_SRV_UNLOAD_LIBRARIES_ERROR = "DHCP4_SRV_UNLOAD_LIBRARIES_ERROR"; extern const isc::log::MessageID DHCP4_STARTED = "DHCP4_STARTED"; extern const isc::log::MessageID DHCP4_STARTING = "DHCP4_STARTING"; extern const isc::log::MessageID DHCP4_START_INFO = "DHCP4_START_INFO"; @@ -291,6 +292,7 @@ const char* values[] = { "DHCP4_SRV_CONSTRUCT_ERROR", "error creating Dhcpv4Srv object, reason: %1", "DHCP4_SRV_D2STOP_ERROR", "error stopping IO with DHCP_DDNS during shutdown: %1", "DHCP4_SRV_DHCP4O6_ERROR", "error stopping IO with DHCPv4o6 during shutdown: %1", + "DHCP4_SRV_UNLOAD_LIBRARIES_ERROR", "error unloading hooks libraries during shutdown: %1", "DHCP4_STARTED", "Kea DHCPv4 server version %1 started", "DHCP4_STARTING", "Kea DHCPv4 server version %1 (%2) starting", "DHCP4_START_INFO", "pid: %1, server port: %2, client port: %3, verbose: %4", diff --git a/src/bin/dhcp4/dhcp4_messages.h b/src/bin/dhcp4/dhcp4_messages.h index 9eb0d014d9..408924a064 100644 --- a/src/bin/dhcp4/dhcp4_messages.h +++ b/src/bin/dhcp4/dhcp4_messages.h @@ -1,4 +1,4 @@ -// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Mon Jun 22 2020 17:28 +// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Thu Jun 25 2020 13:36 #ifndef DHCP4_MESSAGES_H #define DHCP4_MESSAGES_H @@ -142,6 +142,7 @@ extern const isc::log::MessageID DHCP4_SHUTDOWN_REQUEST; extern const isc::log::MessageID DHCP4_SRV_CONSTRUCT_ERROR; extern const isc::log::MessageID DHCP4_SRV_D2STOP_ERROR; extern const isc::log::MessageID DHCP4_SRV_DHCP4O6_ERROR; +extern const isc::log::MessageID DHCP4_SRV_UNLOAD_LIBRARIES_ERROR; extern const isc::log::MessageID DHCP4_STARTED; extern const isc::log::MessageID DHCP4_STARTING; extern const isc::log::MessageID DHCP4_START_INFO; diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index 52cd29ec61..bfc6c372c9 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -828,6 +828,13 @@ stopping IO between the DHCPv4 server and the DHCPv6o6 server. This is probably due to a programmatic error is not likely to impact either server upon restart. The reason for the failure is given within the message. +% DHCP4_SRV_UNLOAD_LIBRARIES_ERROR error unloading hooks libraries during shutdown: %1 +This error message indicates that during shutdown, unloading hooks +libraries failed to close them. If the list of libraries is empty it is +a programmatic error in the server code. If it is not empty it could be +a programmatic error in one of the hooks libraries which could lead to +a crash during finalization. + % DHCP4_STARTED Kea DHCPv4 server version %1 started This informational message indicates that the DHCPv4 server has processed all configuration information and is ready to process diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index db041ee2b0..3b68112b87 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -677,7 +677,18 @@ Dhcpv4Srv::~Dhcpv4Srv() { LeaseMgrFactory::destroy(); // Explicitly unload hooks - HooksManager::unloadLibraries(); + HooksManager::prepareUnloadLibraries(); + if (!HooksManager::unloadLibraries()) { + auto names = HooksManager::getLibraryNames(); + std::string msg; + if (!names.empty()) { + msg = names[0]; + for (size_t i = 1; i < names.size(); ++i) { + msg += std::string(", ") + names[i]; + } + } + LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg); + } } void diff --git a/src/bin/dhcp4/json_config_parser.cc b/src/bin/dhcp4/json_config_parser.cc index 8c0bae4c85..dd0c9ce7d3 100644 --- a/src/bin/dhcp4/json_config_parser.cc +++ b/src/bin/dhcp4/json_config_parser.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -708,6 +709,8 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set, // This occurs last as if it succeeds, there is no easy way to // revert it. As a result, the failure to commit a subsequent // change causes problems when trying to roll back. + HooksManager::prepareUnloadLibraries(); + static_cast(HooksManager::unloadLibraries()); const HooksConfig& libraries = CfgMgr::instance().getStagingCfg()->getHooksConfig(); libraries.loadLibraries(); diff --git a/src/bin/dhcp4/tests/dhcp4to6_ipc_unittest.cc b/src/bin/dhcp4/tests/dhcp4to6_ipc_unittest.cc index 166b53ecb2..13101d61f2 100644 --- a/src/bin/dhcp4/tests/dhcp4to6_ipc_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4to6_ipc_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2020 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 @@ -71,6 +71,19 @@ public: callback_sent_pkt_options_copy_ = std::make_pair(false, false); } + /// @brief Destructor + /// + /// Various cleanups. + virtual ~Dhcp4to6IpcTest() { + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer4_send"); + callback_recv_pkt_.reset(); + callback_sent_pkt_.reset(); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture dtor) unloadLibraries failed" << endl; + } + } + /// @brief Configure DHCP4o6 port. /// /// @param port New port. diff --git a/src/bin/dhcp4/tests/hooks_unittest.cc b/src/bin/dhcp4/tests/hooks_unittest.cc index c59f97897f..0fc7742aff 100644 --- a/src/bin/dhcp4/tests/hooks_unittest.cc +++ b/src/bin/dhcp4/tests/hooks_unittest.cc @@ -106,6 +106,10 @@ public: /// @brief creates Dhcpv4Srv and prepares buffers for callouts HooksDhcpv4SrvTest() { HooksManager::setTestMode(false); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture ctor) unloadLibraries failed" << endl; + } // Allocate new DHCPv6 Server srv_ = new NakedDhcpv4Srv(0); @@ -119,6 +123,9 @@ public: /// @brief destructor (deletes Dhcpv4Srv) virtual ~HooksDhcpv4SrvTest() { + // clear static buffers + resetCalloutBuffers(); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("dhcp4_srv_configured"); HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer4_receive"); HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer4_send"); @@ -132,6 +139,10 @@ public: delete srv_; HooksManager::setTestMode(false); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture dtor) unloadLibraries failed" << endl; + } } /// @brief creates an option with specified option code diff --git a/src/bin/dhcp4/tests/shared_network_unittest.cc b/src/bin/dhcp4/tests/shared_network_unittest.cc index ae7ca5f49e..5cf868c8fb 100644 --- a/src/bin/dhcp4/tests/shared_network_unittest.cc +++ b/src/bin/dhcp4/tests/shared_network_unittest.cc @@ -1344,7 +1344,7 @@ TEST_F(Dhcpv4SharedNetworkTest, parse) { ASSERT_TRUE(status); int rcode; ConstElementPtr comment = config::parseAnswer(rcode, status); - ASSERT_EQ(0, rcode); + ASSERT_EQ(0, rcode) << " comment: " << comment->stringValue(); ASSERT_NO_THROW( { CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess(); cfg_db->setAppendedParameters("universe=4"); diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc index eeb061797f..282cc9e4b1 100644 --- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc +++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc @@ -235,14 +235,21 @@ ControlledDhcpv6Srv::commandLibReloadHandler(const string&, ConstElementPtr) { // stop thread pool (if running) MultiThreadingCriticalSection cs; - /// @todo delete any stored CalloutHandles referring to the old libraries - /// Get list of currently loaded libraries and reload them. - HookLibsCollection loaded = HooksManager::getLibraryInfo(); - bool status = HooksManager::loadLibraries(loaded); - if (!status) { + // Clear the packet queue. + MultiThreadingMgr::instance().getThreadPool().reset(); + + try { + /// Get list of currently loaded libraries and reload them. + HookLibsCollection loaded = HooksManager::getLibraryInfo(); + HooksManager::prepareUnloadLibraries(); + static_cast(HooksManager::unloadLibraries()); + bool status = HooksManager::loadLibraries(loaded); + if (!status) { + isc_throw(Unexpected, "Failed to reload hooks libraries."); + } + } catch (const std::exception& ex) { LOG_ERROR(dhcp6_logger, DHCP6_HOOKS_LIBS_RELOAD_FAIL); - ConstElementPtr answer = isc::config::createAnswer(1, - "Failed to reload hooks libraries."); + ConstElementPtr answer = isc::config::createAnswer(1, ex.what()); return (answer); } ConstElementPtr answer = isc::config::createAnswer(0, diff --git a/src/bin/dhcp6/dhcp6_messages.cc b/src/bin/dhcp6/dhcp6_messages.cc index 341c9bdb6e..6a37909c17 100644 --- a/src/bin/dhcp6/dhcp6_messages.cc +++ b/src/bin/dhcp6/dhcp6_messages.cc @@ -1,4 +1,4 @@ -// File created from ../../../src/bin/dhcp6/dhcp6_messages.mes on Mon Jun 22 2020 17:30 +// File created from ../../../src/bin/dhcp6/dhcp6_messages.mes on Thu Jun 25 2020 14:35 #include #include @@ -140,6 +140,7 @@ extern const isc::log::MessageID DHCP6_SHUTDOWN_REQUEST = "DHCP6_SHUTDOWN_REQUES extern const isc::log::MessageID DHCP6_SOCKET_UNICAST = "DHCP6_SOCKET_UNICAST"; extern const isc::log::MessageID DHCP6_SRV_CONSTRUCT_ERROR = "DHCP6_SRV_CONSTRUCT_ERROR"; extern const isc::log::MessageID DHCP6_SRV_D2STOP_ERROR = "DHCP6_SRV_D2STOP_ERROR"; +extern const isc::log::MessageID DHCP6_SRV_UNLOAD_LIBRARIES_ERROR = "DHCP6_SRV_UNLOAD_LIBRARIES_ERROR"; extern const isc::log::MessageID DHCP6_STANDALONE = "DHCP6_STANDALONE"; extern const isc::log::MessageID DHCP6_STARTED = "DHCP6_STARTED"; extern const isc::log::MessageID DHCP6_STARTING = "DHCP6_STARTING"; @@ -290,6 +291,7 @@ const char* values[] = { "DHCP6_SOCKET_UNICAST", "server is about to open socket on address %1 on interface %2", "DHCP6_SRV_CONSTRUCT_ERROR", "error creating Dhcpv6Srv object, reason: %1", "DHCP6_SRV_D2STOP_ERROR", "error stopping IO with DHCP_DDNS during shutdown: %1", + "DHCP6_SRV_UNLOAD_LIBRARIES_ERROR", "error unloading hooks libraries during shutdown: %1", "DHCP6_STANDALONE", "skipping message queue, running standalone", "DHCP6_STARTED", "Kea DHCPv6 server version %1 started", "DHCP6_STARTING", "Kea DHCPv6 server version %1 (%2) starting", diff --git a/src/bin/dhcp6/dhcp6_messages.h b/src/bin/dhcp6/dhcp6_messages.h index 8294a6e17c..bb9bc10ab5 100644 --- a/src/bin/dhcp6/dhcp6_messages.h +++ b/src/bin/dhcp6/dhcp6_messages.h @@ -1,4 +1,4 @@ -// File created from ../../../src/bin/dhcp6/dhcp6_messages.mes on Mon Jun 22 2020 17:30 +// File created from ../../../src/bin/dhcp6/dhcp6_messages.mes on Thu Jun 25 2020 14:35 #ifndef DHCP6_MESSAGES_H #define DHCP6_MESSAGES_H @@ -141,6 +141,7 @@ extern const isc::log::MessageID DHCP6_SHUTDOWN_REQUEST; extern const isc::log::MessageID DHCP6_SOCKET_UNICAST; extern const isc::log::MessageID DHCP6_SRV_CONSTRUCT_ERROR; extern const isc::log::MessageID DHCP6_SRV_D2STOP_ERROR; +extern const isc::log::MessageID DHCP6_SRV_UNLOAD_LIBRARIES_ERROR; extern const isc::log::MessageID DHCP6_STANDALONE; extern const isc::log::MessageID DHCP6_STARTED; extern const isc::log::MessageID DHCP6_STARTING; diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes index c04cebe0e5..01496c95d6 100644 --- a/src/bin/dhcp6/dhcp6_messages.mes +++ b/src/bin/dhcp6/dhcp6_messages.mes @@ -830,6 +830,13 @@ stopping IO between the DHCPv6 server and the DHCP_DDNS server. This is probably due to a programmatic error is not likely to impact either server upon restart. The reason for the failure is given within the message. +% DHCP6_SRV_UNLOAD_LIBRARIES_ERROR error unloading hooks libraries during shutdown: %1 +This error message indicates that during shutdown, unloading hooks +libraries failed to close them. If the list of libraries is empty it is +a programmatic error in the server code. If it is not empty it could be +a programmatic error in one of the hooks libraries which could lead to +a crash during finalization. + % DHCP6_STANDALONE skipping message queue, running standalone This is a debug message indicating that the IPv6 server is running in standalone mode, not connected to the message queue. Standalone mode diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 0ab2ae93c1..306ae95e36 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -282,7 +282,18 @@ Dhcpv6Srv::~Dhcpv6Srv() { LeaseMgrFactory::destroy(); // Explicitly unload hooks - HooksManager::unloadLibraries(); + HooksManager::prepareUnloadLibraries(); + if (!HooksManager::unloadLibraries()) { + auto names = HooksManager::getLibraryNames(); + std::string msg; + if (!names.empty()) { + msg = names[0]; + for (size_t i = 1; i < names.size(); ++i) { + msg += std::string(", ") + names[i]; + } + } + LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg); + } } void Dhcpv6Srv::shutdown() { diff --git a/src/bin/dhcp6/dhcp6to4_ipc.cc b/src/bin/dhcp6/dhcp6to4_ipc.cc index 0022aced20..68b4970238 100644 --- a/src/bin/dhcp6/dhcp6to4_ipc.cc +++ b/src/bin/dhcp6/dhcp6to4_ipc.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2020 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 @@ -115,6 +115,12 @@ void Dhcp6to4Ipc::handler(int /* fd */) { // Delete previously set arguments callout_handle->deleteAllArguments(); + // Use the RAII wrapper to make sure that the callout handle state is + // reset when this object goes out of scope. All hook points must do + // it to prevent possible circular dependency between the callout + // handle and its arguments. + ScopedCalloutHandleState callout_handle_state(callout_handle); + // Enable copying options from the packet within hook library. ScopedEnableOptionsCopy response6_options_copy(pkt); @@ -153,6 +159,7 @@ void Dhcp6to4Ipc::handler(int /* fd */) { } } -}; // namespace dhcp +} // namespace dhcp + +} // namespace isc -}; // namespace isc diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 9ba6f68f09..f8f8285fec 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -842,6 +843,8 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set, // change causes problems when trying to roll back. const HooksConfig& libraries = CfgMgr::instance().getStagingCfg()->getHooksConfig(); + HooksManager::prepareUnloadLibraries(); + static_cast(HooksManager::unloadLibraries()); libraries.loadLibraries(); } catch (const isc::Exception& ex) { diff --git a/src/bin/dhcp6/tests/dhcp6to4_ipc_unittest.cc b/src/bin/dhcp6/tests/dhcp6to4_ipc_unittest.cc index 307f56e537..46beca27c8 100644 --- a/src/bin/dhcp6/tests/dhcp6to4_ipc_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6to4_ipc_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2020 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 @@ -60,6 +60,18 @@ public: callback_pkt_options_copy_ = false; } + /// @brief Destructor + /// + /// Various cleanups. + virtual ~Dhcp6to4IpcTest() { + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer6_send"); + callback_pkt_.reset(); + bool status = HooksManager::unloadLibraries(); + if (!status) { + std::cerr << "(fixture dtor) unloadLibraries failed" << std::endl; + } + } + /// @brief Configure DHCP4o6 port. /// /// @param port New port. diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc index cd11232ae0..381f589cbc 100644 --- a/src/bin/dhcp6/tests/hooks_unittest.cc +++ b/src/bin/dhcp6/tests/hooks_unittest.cc @@ -123,6 +123,10 @@ public: : Dhcpv6SrvTest() { HooksManager::setTestMode(false); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture ctor) unloadLibraries failed" << endl; + } // Allocate new DHCPv6 Server srv_.reset(new NakedDhcpv6Srv(0)); @@ -138,7 +142,26 @@ public: /// @brief destructor (deletes Dhcpv6Srv) ~HooksDhcpv6SrvTest() { + // Clear static buffers + resetCalloutBuffers(); + + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer6_receive"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("pkt6_receive"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("pkt6_send"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("buffer6_send"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("subnet6_select"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("leases6_committed"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease6_renew"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease6_release"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease6_rebind"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("lease6_decline"); + HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts("host6_identifier"); + HooksManager::setTestMode(false); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture dtor) unloadLibraries failed" << endl; + } } /// @brief creates an option with specified option code @@ -983,7 +1006,7 @@ public: /// that no libraries are loaded and that any marker files are deleted. void reset() { // Unload any previously-loaded libraries. - HooksManager::unloadLibraries(); + EXPECT_TRUE(HooksManager::unloadLibraries()); // Get rid of any marker files. static_cast(remove(LOAD_MARKER_FILE)); diff --git a/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc index df3948b3fa..682e64aa4c 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_hooks_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2015-2020 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 @@ -12,6 +12,8 @@ #include #include +#include + using namespace std; using namespace isc::hooks; using namespace isc::asiolink; @@ -31,8 +33,13 @@ public: } virtual ~HookAllocEngine6Test() { + resetCalloutBuffers(); HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts( "lease6_select"); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture dtor) unloadLibraries failed" << endl; + } } /// @brief clears out buffers, so callouts can store received arguments @@ -181,7 +188,7 @@ TEST_F(HookAllocEngine6Test, lease6_select) { // Initialize Hooks Manager HookLibsCollection libraries; // no libraries at this time - HooksManager::loadLibraries(libraries); + ASSERT_NO_THROW(HooksManager::loadLibraries(libraries)); // Install lease6_select EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( @@ -258,7 +265,7 @@ TEST_F(HookAllocEngine6Test, change_lease6_select) { // Initialize Hooks Manager HookLibsCollection libraries; // no libraries at this time - HooksManager::loadLibraries(libraries); + ASSERT_NO_THROW(HooksManager::loadLibraries(libraries)); // Install a callout EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( @@ -304,7 +311,7 @@ TEST_F(HookAllocEngine6Test, skip_lease6_select) { // Initialize Hooks Manager HookLibsCollection libraries; // no libraries at this time - HooksManager::loadLibraries(libraries); + ASSERT_NO_THROW(HooksManager::loadLibraries(libraries)); // Install a callout EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( @@ -338,12 +345,19 @@ TEST_F(HookAllocEngine6Test, skip_lease6_select) { class HookAllocEngine4Test : public AllocEngine4Test { public: HookAllocEngine4Test() { + // The default context is not used in these tests. + ctx_.callout_handle_.reset(); resetCalloutBuffers(); } virtual ~HookAllocEngine4Test() { + resetCalloutBuffers(); HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts( "lease4_select"); + bool status = HooksManager::unloadLibraries(); + if (!status) { + cerr << "(fixture dtor) unloadLibraries failed" << endl; + } } /// @brief clears out buffers, so callouts can store received arguments @@ -490,7 +504,7 @@ TEST_F(HookAllocEngine4Test, lease4_select) { // Initialize Hooks Manager HookLibsCollection libraries; // no libraries at this time - HooksManager::loadLibraries(libraries); + ASSERT_NO_THROW(HooksManager::loadLibraries(libraries)); // Install lease4_select EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( @@ -565,7 +579,7 @@ TEST_F(HookAllocEngine4Test, change_lease4_select) { // Initialize Hooks Manager HookLibsCollection libraries; // no libraries at this time - HooksManager::loadLibraries(libraries); + ASSERT_NO_THROW(HooksManager::loadLibraries(libraries)); // Install a callout EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( @@ -615,7 +629,7 @@ TEST_F(HookAllocEngine4Test, skip_lease4_select) { // Initialize Hooks Manager HookLibsCollection libraries; // no libraries at this time - HooksManager::loadLibraries(libraries); + ASSERT_NO_THROW(HooksManager::loadLibraries(libraries)); // Install a callout EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( @@ -641,6 +655,6 @@ TEST_F(HookAllocEngine4Test, skip_lease4_select) { checkCalloutHandleReset(ctx.query_); } -}; // namespace test -}; // namespace dhcp -}; // namespace isc +} // namespace test +} // namespace dhcp +} // namespace isc diff --git a/src/lib/hooks/hooks_manager.cc b/src/lib/hooks/hooks_manager.cc index 584a4fdf6f..868f48192c 100644 --- a/src/lib/hooks/hooks_manager.cc +++ b/src/lib/hooks/hooks_manager.cc @@ -135,6 +135,10 @@ HooksManager::loadLibraries(const HookLibsCollection& libraries) { bool HooksManager::unloadLibrariesInternal() { + if (test_mode_) { + return (true); + } + ServerHooks::getServerHooks().getParkingLotsPtr()->clear(); // Keep a weak pointer on the existing library manager collection. @@ -167,6 +171,10 @@ bool HooksManager::unloadLibraries() { void HooksManager::prepareUnloadLibrariesInternal() { + if (test_mode_) { + return; + } + static_cast(lm_collection_->prepareUnloadLibraries()); } diff --git a/src/lib/hooks/tests/hooks_manager_unittest.cc b/src/lib/hooks/tests/hooks_manager_unittest.cc index 282f78916d..6d011093d6 100644 --- a/src/lib/hooks/tests/hooks_manager_unittest.cc +++ b/src/lib/hooks/tests/hooks_manager_unittest.cc @@ -470,6 +470,10 @@ TEST_F(HooksManagerTest, PrePostCalloutTest) { // ... and check that the pre- and post- callout functions don't survive a // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); EXPECT_TRUE(HooksManager::loadLibraries(library_names)); handle = HooksManager::createCalloutHandle(); @@ -519,6 +523,10 @@ TEST_F(HooksManagerTest, TestModeEnabledPrePostSurviveLoad) { // ... and check that the pre- and post- callout functions survive a // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); EXPECT_TRUE(HooksManager::loadLibraries(library_names)); handle = HooksManager::createCalloutHandle(); @@ -569,6 +577,10 @@ TEST_F(HooksManagerTest, TestModeDisabledPrePostDoNotSurviveLoad) { // ... and check that the pre- and post- callout functions don't survive a // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); EXPECT_TRUE(HooksManager::loadLibraries(library_names)); handle = HooksManager::createCalloutHandle(); @@ -616,6 +628,10 @@ TEST_F(HooksManagerTest, TestModeEnabledTooLatePrePostDoNotSurvive) { // ... and check that the pre- and post- callout functions don't survive a // reload. + EXPECT_NO_THROW(HooksManager::prepareUnloadLibraries()); + bool status = false; + EXPECT_NO_THROW(status = HooksManager::unloadLibraries()); + EXPECT_TRUE(status); EXPECT_TRUE(HooksManager::loadLibraries(library_names)); handle = HooksManager::createCalloutHandle();