]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3190] fixed ASAN warnings
authorRazvan Becheriu <razvan@isc.org>
Mon, 5 Feb 2024 10:31:45 +0000 (12:31 +0200)
committerRazvan Becheriu <razvan@isc.org>
Tue, 5 Mar 2024 07:50:05 +0000 (07:50 +0000)
59 files changed:
src/bin/agent/ca_process.cc
src/bin/agent/tests/ca_controller_unittests.cc
src/bin/agent/tests/ca_process_unittests.cc
src/bin/d2/d2_process.cc
src/bin/d2/d2_queue_mgr.cc
src/bin/d2/d2_queue_mgr.h
src/bin/d2/tests/d2_process_unittests.cc
src/bin/d2/tests/d2_queue_mgr_unittests.cc
src/bin/d2/tests/d2_update_mgr_unittests.cc
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/tests/classify_unittest.cc
src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc
src/bin/dhcp4/tests/dhcp4_test_utils.h
src/bin/dhcp4/tests/kea_controller_unittest.cc
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_srv_unittest.cc
src/bin/dhcp6/tests/dhcp6_test_utils.h
src/bin/dhcp6/tests/kea_controller_unittest.cc
src/bin/netconf/http_control_socket.cc
src/bin/netconf/tests/control_socket_unittests.cc
src/bin/netconf/tests/netconf_process_unittests.cc
src/bin/netconf/tests/netconf_unittests.cc
src/hooks/dhcp/high_availability/communication_state.cc
src/hooks/dhcp/high_availability/ha_service.cc
src/hooks/dhcp/high_availability/tests/ha_impl_unittest.cc
src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc
src/hooks/dhcp/high_availability/tests/ha_test.cc
src/hooks/dhcp/high_availability/tests/ha_test.h
src/lib/asiodns/io_fetch.cc
src/lib/asiodns/tests/io_fetch_unittest.cc
src/lib/asiolink/io_service_thread_pool.h
src/lib/asiolink/tcp_socket.h
src/lib/asiolink/tls_socket.h
src/lib/asiolink/udp_socket.h
src/lib/config/cmd_http_listener.cc
src/lib/d2srv/d2_config.h
src/lib/d2srv/dns_client.cc
src/lib/d2srv/dns_client.h
src/lib/d2srv/nc_trans.cc
src/lib/d2srv/tests/dns_client_unittests.cc
src/lib/d2srv/testutils/nc_test_utils.cc
src/lib/d2srv/testutils/nc_test_utils.h
src/lib/dhcp_ddns/ncr_io.cc
src/lib/dhcp_ddns/ncr_io.h
src/lib/dhcp_ddns/ncr_udp.cc
src/lib/dhcp_ddns/tests/ncr_udp_unittests.cc
src/lib/dhcpsrv/tests/memfile_lease_mgr_unittest.cc
src/lib/http/client.cc
src/lib/http/connection_pool.h
src/lib/http/tests/server_client_unittests.cc
src/lib/process/d_controller.cc
src/lib/process/d_controller.h
src/lib/process/d_process.h
src/lib/tcp/mt_tcp_listener_mgr.cc
src/lib/tcp/tests/mt_tcp_listener_mgr_unittests.cc
src/lib/util/stopwatch.cc
src/lib/util/stopwatch.h

index fd36a46e4221d486b051102ae9a0018a005cabbd..9559d84444dc51e569898e9b4ec3090f70507492 100644 (file)
@@ -33,6 +33,7 @@ CtrlAgentProcess::CtrlAgentProcess(const char* name,
 }
 
 CtrlAgentProcess::~CtrlAgentProcess() {
+    garbageCollectListeners(0);
 }
 
 void
@@ -206,7 +207,10 @@ CtrlAgentProcess::garbageCollectListeners(size_t leaving) {
         }
         // We have stopped listeners but there may be some pending handlers
         // related to these listeners. Need to invoke these handlers.
-        getIOService()->poll();
+        try {
+            getIOService()->poll();
+        } catch (...) {
+        }
         // Finally, we're ready to remove no longer used listeners.
         http_listeners_.erase(http_listeners_.begin(),
                               http_listeners_.end() - leaving);
index 1e0c58c30ee36b909527c9314d97b0e5db895322..9a18c27a0a0fbb671dec336fd0f9d7c40c98e820 100644 (file)
@@ -188,7 +188,6 @@ TEST_F(CtrlAgentControllerTest, basicInstanceTesting) {
     EXPECT_FALSE(checkProcess());
 }
 
-
 // Tests basic command line processing.
 // Verifies that:
 // 1. Standard command line options are supported.
@@ -680,7 +679,6 @@ TEST_F(CtrlAgentControllerTest, configReloadFileValid) {
     answer = CtrlAgentCommandMgr::instance().handleCommand("config-reload",
                                                            params, cmd);
 
-
     // Verify the reload was successful.
     string expected = "{ \"result\": 0, \"text\": "
         "\"Configuration applied successfully.\" }";
@@ -785,7 +783,6 @@ TEST_F(CtrlAgentControllerTest, shutdown) {
     ctrl->deregisterCommands();
 }
 
-
 TEST_F(CtrlAgentControllerTest, shutdownExitValue) {
     ASSERT_NO_THROW(initProcess());
     EXPECT_TRUE(checkProcess());
index ecb256318850f976863573d5e3ce7c67e9513ee3..3d708c3e43be6e7cae345f95ac2433c3f4b96251 100644 (file)
@@ -84,7 +84,13 @@ TEST_F(CtrlAgentProcessTest, shutdown) {
     time_duration elapsed = stop - start;
     EXPECT_TRUE(elapsed.total_milliseconds() >= 100 &&
                 elapsed.total_milliseconds() <= 400);
-}
 
+    timer.cancel();
+    getIOService()->restart();
+    try {
+        getIOService()->poll();
+    } catch (...) {
+    }
+}
 
 }
index 426f95f2a924d13b6319713a676f087b62afbe23..fb96bce4bd5107e2d732de305e652bfc6f324e00 100644 (file)
@@ -439,6 +439,9 @@ D2Process::reconfigureQueueMgr() {
 }
 
 D2Process::~D2Process() {
+    queue_mgr_->stopListening();
+    auto f = [](D2QueueMgrPtr) {};
+    getIOService()->post(std::bind(f, queue_mgr_));
 }
 
 D2CfgMgrPtr
index 12efe742e8fcb5b915fb3cf7967cf08d7416f455..a598893d70867b8b4c627cdc4dd14949e603ef91 100644 (file)
@@ -178,7 +178,6 @@ D2QueueMgr::updateStopState() {
               DHCP_DDNS_QUEUE_MGR_STOPPED);
 }
 
-
 void
 D2QueueMgr::removeListener() {
     // Force our managing layer(s) to stop us properly first.
@@ -224,7 +223,6 @@ D2QueueMgr::dequeueAt(const size_t index) {
     ncr_queue_.erase(pos);
 }
 
-
 void
 D2QueueMgr::dequeue() {
     if (getQueueSize() ==  0) {
index bbd95ea01656778ad8c02f3ab3b10139b3711478..4abf3c54d1c91494445ef17639b982404e62696e 100644 (file)
@@ -40,7 +40,6 @@ public:
         isc::Exception(file, line, what) { };
 };
 
-
 /// @brief Thrown if the request queue is full when an enqueue is attempted.
 /// @todo use or remove it.
 class D2QueueMgrQueueFull : public isc::Exception {
@@ -63,7 +62,6 @@ public:
         isc::Exception(file, line, what) { };
 };
 
-
 /// @brief D2QueueMgr creates and manages a queue of DNS update requests.
 ///
 /// D2QueueMgr is a class specifically designed as an integral part of DHCP-DDNS.
@@ -217,8 +215,8 @@ public:
     /// @param ncr is a pointer to the newly received NameChangeRequest if
     /// result is NameChangeListener::SUCCESS.  It is indeterminate other
     /// wise.
-    virtual void operator ()(const dhcp_ddns::NameChangeListener::Result result,
-                             dhcp_ddns::NameChangeRequestPtr& ncr);
+    virtual void operator()(const dhcp_ddns::NameChangeListener::Result result,
+                            dhcp_ddns::NameChangeRequestPtr& ncr);
 
     /// @brief Stops listening for requests.
     ///
@@ -234,7 +232,6 @@ public:
     /// @throw D2QueueMgrError if stop_state is a valid stop state.
     void stopListening(const State target_stop_state = STOPPED);
 
-
     /// @brief Deletes the current listener
     ///
     /// This method will delete the current listener and returns the manager
index bc6be18a172912c6685431d0878e468262a54e23..8bbaf35ff605c7645380314818c7c645873a37ba 100644 (file)
@@ -113,9 +113,9 @@ public:
         const D2QueueMgrPtr& queue_mgr = getD2QueueMgr();
 
         // If queue manager isn't in the RUNNING state, return failure.
-        if (D2QueueMgr::RUNNING !=  queue_mgr->getMgrState()) {
+        if (D2QueueMgr::RUNNING != queue_mgr->getMgrState()) {
             return (::testing::AssertionFailure(::testing::Message() <<
-                                               "queue manager did not start"));
+                                                "queue manager did not start"));
         }
 
         //  Good to go.
@@ -578,6 +578,13 @@ TEST_F(D2ProcessTest, normalShutdown) {
     time_duration elapsed = stop - start;
     EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
                 elapsed.total_milliseconds() <= 2200);
+
+    timer.cancel();
+    getIOService()->restart();
+    try {
+        getIOService()->poll();
+    } catch (...) {
+    }
 }
 
 /// @brief Verifies that an "uncaught" exception thrown during event loop
@@ -602,6 +609,13 @@ TEST_F(D2ProcessTest, fatalErrorShutdown) {
     time_duration elapsed = stop - start;
     EXPECT_TRUE(elapsed.total_milliseconds() >= 1900 &&
                 elapsed.total_milliseconds() <= 2200);
+
+    timer.cancel();
+    getIOService()->restart();
+    try {
+        getIOService()->poll();
+    } catch (...) {
+    }
 }
 
 /// @brief Used to permit visual inspection of logs to ensure
index dbbeec807b3fe2fd24e1dbcddfc65251e9d13dc2..5da5fe040f12a2eedd2970684bd38f6e949518c9 100644 (file)
@@ -232,6 +232,15 @@ public:
                           TEST_TIMEOUT);
     }
 
+    virtual ~QueueMgrUDPTest() {
+        test_timer_.cancel();
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+    }
+
     void reset_results() {
         sent_ncrs_.clear();
         received_ncrs_.clear();
index 920ccc884e68b2b1c93eb9ec4d5b77f2470680b1..df8de60e2866ea824498c0ea2a02e8b34526904f 100644 (file)
@@ -71,6 +71,7 @@ public:
     D2UpdateMgrWrapperPtr update_mgr_;
     std::vector<NameChangeRequestPtr> canned_ncrs_;
     size_t canned_count_;
+    boost::shared_ptr<FauxServer> server_;
 
     D2UpdateMgrTest() {
         queue_mgr_.reset(new D2QueueMgr(io_service_));
@@ -82,6 +83,14 @@ public:
     }
 
     ~D2UpdateMgrTest() {
+        if (server_) {
+            server_->stop();
+        }
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Creates a list of valid NameChangeRequest.
@@ -184,11 +193,11 @@ public:
         TransactionList::iterator it = update_mgr_->transactionListBegin();
         while (it != update_mgr_->transactionListEnd()) {
             if (((*it).second)->isModelWaiting()) {
-                return true;
+                return (true);
             }
         }
 
-        return false;
+        return (false);
     }
 
     /// @brief Process events until all requests have been completed.
@@ -692,8 +701,8 @@ TEST_F(D2UpdateMgrTest, addTransaction) {
 
     // Create a server based on the transaction's current server, and
     // start it listening.
-    FauxServer server(io_service_, *(trans->getCurrentServer()));
-    server.receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
+    server_.reset(new FauxServer(io_service_, *(trans->getCurrentServer())));
+    server_->receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
 
     // Run sweep and IO until everything is done.
     processAll();
@@ -749,8 +758,8 @@ TEST_F(D2UpdateMgrTest, removeTransaction) {
 
     // Create a server based on the transaction's current server, and
     // start it listening.
-    FauxServer server(io_service_, *(trans->getCurrentServer()));
-    server.receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
+    server_.reset(new FauxServer(io_service_, *(trans->getCurrentServer())));
+    server_->receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
 
     // Run sweep and IO until everything is done.
     processAll();
@@ -797,8 +806,8 @@ TEST_F(D2UpdateMgrTest, errorTransaction) {
     ASSERT_TRUE(trans->getCurrentServer());
 
     // Create a server and start it listening.
-    FauxServer server(io_service_, *(trans->getCurrentServer()));
-    server.receive(FauxServer::CORRUPT_RESP);
+    server_.reset(new FauxServer(io_service_, *(trans->getCurrentServer())));
+    server_->receive(FauxServer::CORRUPT_RESP);
 
     // Run sweep and IO until everything is done.
     processAll();
@@ -836,8 +845,8 @@ TEST_F(D2UpdateMgrTest, multiTransaction) {
     // that all of configured servers have the same address.
     // and start it listening.
     asiolink::IOAddress server_ip("127.0.0.1");
-    FauxServer server(io_service_, server_ip, 5301);
-    server.receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
+    server_.reset(new FauxServer(io_service_, server_ip, 5301));
+    server_->receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
 
     // Run sweep and IO until everything is done.
     processAll();
@@ -908,8 +917,8 @@ TEST_F(D2UpdateMgrTest, simpleAddTransaction) {
 
     // Create a server based on the transaction's current server, and
     // start it listening.
-    FauxServer server(io_service_, *(trans->getCurrentServer()));
-    server.receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
+    server_.reset(new FauxServer(io_service_, *(trans->getCurrentServer())));
+    server_->receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
 
     // Run sweep and IO until everything is done.
     processAll();
@@ -966,8 +975,8 @@ TEST_F(D2UpdateMgrTest, simpleRemoveTransaction) {
 
     // Create a server based on the transaction's current server, and
     // start it listening.
-    FauxServer server(io_service_, *(trans->getCurrentServer()));
-    server.receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
+    server_.reset(new FauxServer(io_service_, *(trans->getCurrentServer())));
+    server_->receive(FauxServer::USE_RCODE, dns::Rcode::NOERROR());
 
     // Run sweep and IO until everything is done.
     processAll();
index d726322ef6a6fc72830ca2ab97832505f96a6a8b..80bba69d43cf702c0911d80295bfcd80e321e616 100644 (file)
@@ -705,6 +705,11 @@ Dhcpv4Srv::~Dhcpv4Srv() {
         }
         LOG_ERROR(dhcp4_logger, DHCP4_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
     }
+    io_service_->restart();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 }
 
 void
index d759245d4a0be87e7bd3067d906db86828fc5141..7f81dbd17214cc64d71e2ba89b131660ec5ae844 100644 (file)
@@ -521,7 +521,6 @@ public:
     IfaceMgrTestConfig iface_mgr_test_config_;
 };
 
-
 // This test checks that an incoming DISCOVER that does not match any classes
 // will get the fixed fields empty.
 TEST_F(ClassifyTest, fixedFieldsDiscoverNoClasses) {
@@ -538,7 +537,6 @@ TEST_F(ClassifyTest, fixedFieldsInformNoClasses) {
     testFixedFields(CONFIGS[0], DHCPINFORM, OptionPtr(), "0.0.0.0", "", "");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a class that has
 // next-server specified will result in a response that has the next-server set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverNextServer) {
@@ -561,7 +559,6 @@ TEST_F(ClassifyTest, fixedFieldsInformNextServer) {
     testFixedFields(CONFIGS[0], DHCPINFORM, pxe, "1.2.3.4", "", "");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a class that has
 // server-hostname specified will result in a response that has the sname field set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverHostname) {
@@ -584,7 +581,6 @@ TEST_F(ClassifyTest, fixedFieldsInformHostname) {
     testFixedFields(CONFIGS[0], DHCPINFORM, pxe, "0.0.0.0", "deneb", "");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a class that has
 // boot-file-name specified will result in a response that has the filename field set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverFile1) {
@@ -607,7 +603,6 @@ TEST_F(ClassifyTest, fixedFieldsInformFile1) {
     testFixedFields(CONFIGS[0], DHCPDISCOVER, pxe, "0.0.0.0", "", "pxelinux.0");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a different class that has
 // boot-file-name specified will result in a response that has the filename field set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverFile2) {
@@ -703,7 +698,6 @@ TEST_F(ClassifyTest, fixedFieldsInformNoClasses2) {
     testFixedFields(CONFIGS[2], DHCPINFORM, OptionPtr(), "0.0.0.0", "", "");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a class that has
 // next-server specified will result in a response that has the next-server set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverNextServer2) {
@@ -726,7 +720,6 @@ TEST_F(ClassifyTest, fixedFieldsInformNextServer2) {
     testFixedFields(CONFIGS[2], DHCPINFORM, pxe, "1.2.3.4", "", "");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a class that has
 // boot-file-name specified will result in a response that has the filename field set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverFile21) {
@@ -749,7 +742,6 @@ TEST_F(ClassifyTest, fixedFieldsInformFile21) {
     testFixedFields(CONFIGS[2], DHCPDISCOVER, pxe, "0.0.0.0", "", "pxelinux.0");
 }
 
-
 // This test checks that an incoming DISCOVER that does match a different class that has
 // boot-file-name specified will result in a response that has the filename field set.
 TEST_F(ClassifyTest, fixedFieldsDiscoverFile22) {
@@ -800,7 +792,6 @@ TEST_F(ClassifyTest, fixedFieldsInformNextServer3) {
     testFixedFields(CONFIGS[3], DHCPINFORM, pxe, "0.0.0.0", "", "");
 }
 
-
 // Class pxe2 is only-if-required but the subnet requires its evaluation
 TEST_F(ClassifyTest, fixedFieldsDiscoverHostname3) {
     OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0007));
index 2f852022209c3dc30f061758be81d15e6df338f1..04a567baf97034400a5dcd6bc4e9bd5dad969d9d 100644 (file)
@@ -135,6 +135,7 @@ public:
         CommandMgr::instance().setConnectionTimeout(TIMEOUT_DHCP_SERVER_RECEIVE_COMMAND);
 
         server_.reset();
+        reset();
         IfaceMgr::instance().setTestMode(false);
         IfaceMgr::instance().setDetectCallback(std::bind(&IfaceMgr::checkDetectIfaces,
                                                IfaceMgr::instancePtr().get(), ph::_1));
@@ -806,7 +807,8 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configSet) {
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output-options\": [{ \n"
-        "                \"output\": \"/dev/null\" \n"
+        "                \"output\": \"/dev/null\", \n"
+        "                \"maxsize\": 0"
         "            }] \n"
         "        }] \n";
 
@@ -1021,7 +1023,8 @@ TEST_F(CtrlChannelDhcpv4SrvTest, configTest) {
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output-options\": [{ \n"
-        "                \"output\": \"/dev/null\" \n"
+        "                \"output\": \"/dev/null\", \n"
+        "                \"maxsize\": 0"
         "            }] \n"
         "        }] \n";
 
index 7063961526a6cde07bcc30a09aa0d0cdb20c147e..73cae9b8e7cd0b20894b9c0555f8c7d5dd4bba89 100644 (file)
@@ -2874,15 +2874,6 @@ Dhcpv4SrvTest::loadConfigFile(const string& path) {
                 return (ConfigBackendDHCPv4Ptr());
             });
 
-    // TimerMgr uses IO service to run asynchronous timers.
-    TimerMgr::instance()->setIOService(srv.getIOService());
-
-    // CommandMgr uses IO service to run asynchronous socket operations.
-    CommandMgr::instance().setIOService(srv.getIOService());
-
-    // DatabaseConnection uses IO service to run asynchronous timers.
-    DatabaseConnection::setIOService(srv.getIOService());
-
     Parser4Context parser;
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parser.parseFile(path, Parser4Context::PARSER_DHCP4));
index dce7e2ca44fa5b0f2896bf1d8dad56abf87d014c..2db8a1ac5a452fb5c0166170c7a28d1c8a3f87b0 100644 (file)
@@ -25,6 +25,7 @@
 #include <dhcp4/parser_context.h>
 #include <asiolink/io_address.h>
 #include <cc/command_interpreter.h>
+#include <config/command_mgr.h>
 #include <util/multi_threading_mgr.h>
 #include <list>
 
@@ -126,6 +127,10 @@ public:
         server_id_.reset(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
                                             asiolink::IOAddress("192.0.3.1")));
         db::DatabaseConnection::setIOService(getIOService());
+
+        dhcp::TimerMgr::instance()->setIOService(getIOService());
+
+        config::CommandMgr::instance().setIOService(getIOService());
     }
 
     /// @brief Returns fixed server identifier assigned to the naked server
@@ -199,6 +204,14 @@ public:
     }
 
     virtual ~NakedDhcpv4Srv() {
+        // Close the lease database
+        isc::dhcp::LeaseMgrFactory::destroy();
+
+        getIOService()->restart();
+        try {
+            getIOService()->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Runs processing DHCPDISCOVER.
index f5877d8f363e4ef5ac5cd6414b638f0d0dcbbc42..1d76f4c581df28d61148874c1fab3c6744050bd3 100644 (file)
@@ -201,6 +201,7 @@ public:
 
     ~JSONFileBackendTest() {
         LeaseMgrFactory::destroy();
+        isc::log::setDefaultLoggingOutput();
         static_cast<void>(remove(TEST_FILE));
         static_cast<void>(remove(TEST_INCLUDE));
     };
index 2fdbafd2fc2092204ea0b46fea0c7523284f82eb..b4db600e5e532228193f88c3e7441d0c08eef898 100644 (file)
@@ -302,6 +302,11 @@ Dhcpv6Srv::~Dhcpv6Srv() {
         }
         LOG_ERROR(dhcp6_logger, DHCP6_SRV_UNLOAD_LIBRARIES_ERROR).arg(msg);
     }
+    io_service_->restart();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 }
 
 void Dhcpv6Srv::shutdown() {
index a00f0c713536a9002d3a3371676b63eef8feeab8..1150b1f577d2442d530cc94bcf93dc953df0e234 100644 (file)
@@ -9,6 +9,7 @@
 #include <asiolink/io_address.h>
 #include <cc/command_interpreter.h>
 #include <config/command_mgr.h>
+#include <config/timeouts.h>
 #include <dhcp/libdhcp++.h>
 #include <dhcp/testutils/iface_mgr_test_config.h>
 #include <dhcpsrv/cfgmgr.h>
@@ -162,6 +163,13 @@ public:
 
     /// @brief Destructor
     ~CtrlChannelDhcpv6SrvTest() {
+        LeaseMgrFactory::destroy();
+        StatsMgr::instance().removeAll();
+
+        CommandMgr::instance().closeCommandSocket();
+        CommandMgr::instance().deregisterAll();
+        CommandMgr::instance().setConnectionTimeout(TIMEOUT_DHCP_SERVER_RECEIVE_COMMAND);
+
         server_.reset();
         reset();
         IfaceMgr::instance().setTestMode(false);
@@ -716,7 +724,8 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configSet) {
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output-options\": [{ \n"
-        "                \"output\": \"/dev/null\" \n"
+        "                \"output\": \"/dev/null\", \n"
+        "                \"maxsize\": 0"
         "            }] \n"
         "        }] \n";
 
@@ -932,7 +941,8 @@ TEST_F(CtrlChannelDhcpv6SrvTest, configTest) {
         "            \"name\": \"kea\", \n"
         "            \"severity\": \"FATAL\", \n"
         "            \"output-options\": [{ \n"
-        "                \"output\": \"/dev/null\" \n"
+        "                \"output\": \"/dev/null\", \n"
+        "                \"maxsize\": 0"
         "            }] \n"
         "        }] \n";
 
index 13234df3a978b872db42b58d7614be004426641d..1cc9abf2393b6a6ac8d918bd72d296570f602bbb 100644 (file)
@@ -243,15 +243,6 @@ Dhcpv6SrvTest::loadConfigFile(const string& path) {
                 return (ConfigBackendDHCPv6Ptr());
             });
 
-    // TimerMgr uses IO service to run asynchronous timers.
-    TimerMgr::instance()->setIOService(srv.getIOService());
-
-    // CommandMgr uses IO service to run asynchronous socket operations.
-    CommandMgr::instance().setIOService(srv.getIOService());
-
-    // DatabaseConnection uses IO service to run asynchronous timers.
-    DatabaseConnection::setIOService(srv.getIOService());
-
     Parser6Context parser;
     ConstElementPtr json;
     ASSERT_NO_THROW(json = parser.parseFile(path, Parser6Context::PARSER_DHCP6));
index da23b936f5bd9b2cf9a21a4260e8a8b2e82f3cae..57d2894bc303ff2264e28555b5b127533dac2be5 100644 (file)
@@ -29,6 +29,7 @@
 #include <dhcpsrv/lease_mgr.h>
 #include <dhcpsrv/lease_mgr_factory.h>
 #include <hooks/hooks_manager.h>
+#include <config/command_mgr.h>
 #include <util/multi_threading_mgr.h>
 
 #include <list>
@@ -136,6 +137,10 @@ public:
         std::string memfile = "type=memfile universe=6 persist=false";
         isc::dhcp::LeaseMgrFactory::create(memfile);
         db::DatabaseConnection::setIOService(getIOService());
+
+        dhcp::TimerMgr::instance()->setIOService(getIOService());
+
+        config::CommandMgr::instance().setIOService(getIOService());
     }
 
     /// @brief fakes packet reception
@@ -209,6 +214,12 @@ public:
     virtual ~NakedDhcpv6Srv() {
         // Close the lease database
         isc::dhcp::LeaseMgrFactory::destroy();
+
+        getIOService()->restart();
+        try {
+            getIOService()->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Processes incoming Solicit message.
index 068fc96845a77b47b0442402ba286921fd63da44..960890131d1dad8b0148a14d58fed473c19f0921 100644 (file)
@@ -188,8 +188,7 @@ public:
 
 class JSONFileBackendTest : public dhcp::test::BaseServerTest {
 public:
-    JSONFileBackendTest()
-        : BaseServerTest() {
+    JSONFileBackendTest() {
     }
 
     ~JSONFileBackendTest() {
index 197c51916c2dfa130aafb03577624b9a7b2e6022..801cfb5b9807aeeb13b5145bd294d2d05d305e8d 100644 (file)
@@ -101,6 +101,13 @@ HttpControlSocket::sendCommand(ConstElementPtr command) {
     // Perform this synchronously.
     io_service->run();
 
+    client.stop();
+    io_service->restart();
+    try {
+        io_service->poll();
+    } catch (...) {
+    }
+
     if (received_ec) {
         // Got an error code.
         isc_throw(ControlSocketError, "communication error (code): "
index 996bcbae40447a84b186df440180dd4509752305..10f36f71da7c339247928df9510f65e3d770704d 100644 (file)
@@ -157,11 +157,12 @@ public:
             thread_->join();
             thread_.reset();
         }
-        // io_service must be stopped after the thread returns,
-        // otherwise the thread may never return if it is
-        // waiting for the completion of some asynchronous tasks.
-        io_service_->stop();
         removeUnixSocketFile();
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Returns socket file path.
@@ -525,10 +526,15 @@ public:
             thread_->join();
             thread_.reset();
         }
-        // io_service must be stopped after the thread returns,
-        // otherwise the thread may never return if it is
-        // waiting for the completion of some asynchronous tasks.
-        io_service_->stop();
+        if (listener_) {
+            listener_->stop();
+        }
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+        listener_.reset();
     }
 
     /// @brief Returns socket URL.
@@ -568,7 +574,7 @@ public:
             while (!isStopping()) {
                 io_service_->runOne();
             }
-            // Main thread signalled that the thread should
+            // Main thread signaled that the thread should
             // terminate. Launch any outstanding IO service
             // handlers.
             io_service_->poll();
index 3cfdbd040a1892025236367ad58fee3e6191c179..a8c85cf6f17b9982993627bd4e256c955462bdf4 100644 (file)
@@ -80,6 +80,12 @@ TEST_F(NetconfProcessTest, shutdown) {
     time_duration elapsed = stop - start;
     EXPECT_TRUE(elapsed.total_milliseconds() >= 100 &&
                 elapsed.total_milliseconds() <= 400);
+    timer.cancel();
+    getIOService()->restart();
+    try {
+        getIOService()->poll();
+    } catch (...) {
+    }
 }
 
 }
index fd3340d33ca5e5da9f198b37cee32c9289046eed..989034028fb993bd41bdac2160898c8714677fdd 100644 (file)
@@ -121,11 +121,6 @@ public:
             thread_->join();
             thread_.reset();
         }
-        // io_service must be stopped after the thread returns,
-        // otherwise the thread may never return if it is
-        // waiting for the completion of some asynchronous tasks.
-        io_service_->stop();
-        io_service_.reset();
         if (agent_) {
             clearYang(agent_);
             agent_->clear();
@@ -135,6 +130,11 @@ public:
         responses_.clear();
         removeUnixSocketFile();
         SysrepoSetup::cleanSharedMemory();
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Returns socket file path.
index 38b7566df3a2faacbd881aa14bf38db8dc4c7fa4..2e9d1beae449abb2e9dce7ff09b76453646905cd 100644 (file)
@@ -229,6 +229,8 @@ void
 CommunicationState::stopHeartbeatInternal() {
     if (timer_) {
         timer_->cancel();
+        auto f = [](IntervalTimerPtr) {};
+        io_service_->post(std::bind(f, timer_));
         timer_.reset();
         interval_ = 0;
         heartbeat_impl_ = 0;
index d148afa81ee2ffeff2ba432a85f2cde0fb5a8d61..3ec6d8ca154014eb3976c62e1d997991656f35a0 100644 (file)
@@ -2448,6 +2448,14 @@ HAService::synchronize(std::string& status_message, const std::string& server_na
     // End measuring duration.
     stopwatch.stop();
 
+    client.stop();
+
+    io_service->restart();
+    try {
+        io_service->poll();
+    } catch (...) {
+    }
+
     // If an error message has been recorded, return an error to the controlling
     // client.
     if (!status_message.empty()) {
@@ -2586,6 +2594,14 @@ HAService::sendLeaseUpdatesFromBacklog() {
     // End measuring duration.
     stopwatch.stop();
 
+    client.stop();
+
+    io_service->restart();
+    try {
+        io_service->poll();
+    } catch (...) {
+    }
+
     if (updates_successful) {
         LOG_INFO(ha_logger, HA_LEASES_BACKLOG_SUCCESS)
             .arg(config_->getThisServerName())
@@ -2665,6 +2681,14 @@ HAService::sendHAReset() {
     // Run the IO service until it is stopped by the callback. This makes it synchronous.
     io_service->run();
 
+    client.stop();
+
+    io_service->restart();
+    try {
+        io_service->poll();
+    } catch (...) {
+    }
+
     return (reset_successful);
 }
 
@@ -2824,6 +2848,14 @@ HAService::processMaintenanceStart() {
     // makes it synchronous.
     io_service->run();
 
+    client.stop();
+
+    io_service->restart();
+    try {
+        io_service->poll();
+    } catch (...) {
+    }
+
     // If there was a communication problem with the partner we assume that
     // the partner is already down while we receive this command.
     if (captured_ec || (captured_rcode == CONTROL_RESULT_ERROR)) {
@@ -2938,6 +2970,14 @@ HAService::processMaintenanceCancel() {
     // makes it synchronous.
     io_service->run();
 
+    client.stop();
+
+    io_service->restart();
+    try {
+        io_service->poll();
+    } catch (...) {
+    }
+
     // There was an error in communication with the partner or the
     // partner was unable to revert its state.
     if (!error_message.empty()) {
index 0f5c18f1724f35a8e67d430cb41b7f09fe4e2276..4f7eb1a5a30615417959e079bb68ab74aa172cfb 100644 (file)
@@ -74,6 +74,25 @@ public:
 /// @brief Test fixture class for @c HAImpl.
 class HAImplTest : public HATest {
 public:
+    /// @brief Constructor.
+    HAImplTest() {
+    }
+
+    /// @brief Destructor.
+    ~HAImplTest() {
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+        ha_impl_.reset();
+        test_ha_impl_.reset();
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+    }
 
     /// @brief Tests handler of a ha-sync command.
     ///
@@ -84,65 +103,85 @@ public:
     /// @param expected_response expected text response.
     void testSynchronizeHandler(const std::string& ha_sync_command,
                                 const std::string& expected_response) {
-        HAImpl ha_impl;
-        ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+        io_service_.reset(new IOService);
+        ha_impl_.reset(new HAImpl());
+        ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
         // Starting the service is required prior to running any callouts.
         NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-        ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                              HAServerType::DHCPv4));
+        ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                                HAServerType::DHCPv4));
 
         ConstElementPtr command = Element::fromJSON(ha_sync_command);
 
         CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
         callout_handle->setArgument("command", command);
 
-        ASSERT_NO_THROW(ha_impl.synchronizeHandler(*callout_handle));
+        ASSERT_NO_THROW(ha_impl_->synchronizeHandler(*callout_handle));
 
         ConstElementPtr response;
         callout_handle->getArgument("response", response);
         ASSERT_TRUE(response);
 
         checkAnswer(response, CONTROL_RESULT_ERROR, expected_response);
+        callout_handle.reset();
+
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+        ha_impl_.reset();
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
     }
+
+    /// @brief HA Instance under test.
+    boost::shared_ptr<TestHAImpl> test_ha_impl_;
+
+    /// @brief HA Instance under test.
+    boost::shared_ptr<HAImpl> ha_impl_;
 };
 
 // Tests that HAService object is created for DHCPv4 service.
 TEST_F(HAImplTest, startServices) {
     // Valid configuration must be provided prior to starting the service.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Network state is also required.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
 
     // Start the service for DHCPv4 server.
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // Make sure that the HA service has been created for the requested
     // server type.
-    ASSERT_TRUE(ha_impl.services_);
-    EXPECT_EQ(HAServerType::DHCPv4, ha_impl.services_->get()->getServerType());
+    ASSERT_TRUE(test_ha_impl_->services_);
+    EXPECT_EQ(HAServerType::DHCPv4, test_ha_impl_->services_->get()->getServerType());
 }
 
 // Tests that HAService object is created for DHCPv6 service.
 TEST_F(HAImplTest, startServices6) {
     // Valid configuration must be provided prior to starting the service.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Network state is also required.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
 
     // Start the service for DHCPv4 server.
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // Make sure that the HA service has been created for the requested
     // server type.
-    ASSERT_TRUE(ha_impl.services_);
-    EXPECT_EQ(HAServerType::DHCPv6, ha_impl.services_->get()->getServerType());
+    ASSERT_TRUE(test_ha_impl_->services_);
+    EXPECT_EQ(HAServerType::DHCPv6, test_ha_impl_->services_->get()->getServerType());
 }
 
 // Tests for buffer4_receive callout implementation.
@@ -152,17 +191,17 @@ TEST_F(HAImplTest, buffer4Receive) {
     ConstElementPtr ha_config = createValidJsonConfiguration(HAConfig::HOT_STANDBY);
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // Initially the HA service is in the waiting state and serves no scopes.
     // We need to explicitly enable the scope to be served.
-    ha_impl.services_->get()->serveDefaultScopes();
+    test_ha_impl_->services_->get()->serveDefaultScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -198,7 +237,7 @@ TEST_F(HAImplTest, buffer4Receive) {
     callout_handle->setArgument("query4", query4);
 
     // Invoke the buffer4_receive callout.
-    ASSERT_NO_THROW(ha_impl.buffer4Receive(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->buffer4Receive(*callout_handle));
 
     // The BOOTP messages are not supported so trying to unpack the message
     // should trigger an error. The callout should set the next step to
@@ -233,7 +272,7 @@ TEST_F(HAImplTest, buffer4Receive) {
     callout_handle->setArgument("query4", query4);
 
     // Invoke the callout again.
-    ASSERT_NO_THROW(ha_impl.buffer4Receive(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->buffer4Receive(*callout_handle));
 
     // This time the callout should set the next step to SKIP to indicate to
     // the DHCP server that the message has been already parsed.
@@ -259,19 +298,19 @@ TEST_F(HAImplTest, subnet4Select) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -291,7 +330,7 @@ TEST_F(HAImplTest, subnet4Select) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // Make sure that the request was not dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -313,19 +352,19 @@ TEST_F(HAImplTest, subnet4SelectSharedNetwork) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -348,7 +387,7 @@ TEST_F(HAImplTest, subnet4SelectSharedNetwork) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // Make sure that the request was not dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -370,13 +409,13 @@ TEST_F(HAImplTest, subnet4SelectSingleRelationship) {
     ConstElementPtr ha_config = createValidJsonConfiguration(HAConfig::HOT_STANDBY);
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -394,7 +433,7 @@ TEST_F(HAImplTest, subnet4SelectSingleRelationship) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // The request should not be dropped and there should be no classes assigned
     // because the callout didn't call the HAService::inScope function.
@@ -408,19 +447,19 @@ TEST_F(HAImplTest, subnet4SelectDropNoServerName) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -437,7 +476,7 @@ TEST_F(HAImplTest, subnet4SelectDropNoServerName) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // The request should be dropped and no classes assigned to it.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -450,19 +489,19 @@ TEST_F(HAImplTest, subnet4SelectDropInvalidServerNameType) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -483,7 +522,7 @@ TEST_F(HAImplTest, subnet4SelectDropInvalidServerNameType) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // The request should be dropped and no classes assigned to it.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -496,18 +535,18 @@ TEST_F(HAImplTest, subnet4SelectDropNotInScope) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // This server serves server1/server2 scopes but not server3/server4 scopes.
     // The request should be dropped because the subnet will be associated with
     // the server3.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -528,7 +567,7 @@ TEST_F(HAImplTest, subnet4SelectDropNotInScope) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // The request should be dropped because the server is not responsible for
     // this scope currently.
@@ -544,16 +583,16 @@ TEST_F(HAImplTest, subnet4SelectNoSubnet) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -570,7 +609,7 @@ TEST_F(HAImplTest, subnet4SelectNoSubnet) {
     callout_handle->setArgument("subnet4", subnet4);
 
     // Invoke the subnet4_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet4Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet4Select(*callout_handle));
 
     // No subnet has been selected and we have multiple relationships. We
     // expect that the server drops the packet.
@@ -587,17 +626,17 @@ TEST_F(HAImplTest, buffer6Receive) {
     ConstElementPtr ha_config = createValidJsonConfiguration(HAConfig::HOT_STANDBY);
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // Initially the HA service is in the waiting state and serves no scopes.
     // We need to explicitly enable the scope to be served.
-    ha_impl.services_->get()->serveDefaultScopes();
+    test_ha_impl_->services_->get()->serveDefaultScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -618,7 +657,7 @@ TEST_F(HAImplTest, buffer6Receive) {
     callout_handle->setArgument("query6", query6);
 
     // Invoke the buffer6_receive callout.
-    ASSERT_NO_THROW(ha_impl.buffer6Receive(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->buffer6Receive(*callout_handle));
 
     // Our DHCP messages contains no transaction id so it should cause
     // parsing error. The next step is set to DROP for malformed messages.
@@ -650,7 +689,7 @@ TEST_F(HAImplTest, buffer6Receive) {
     callout_handle->setArgument("query6", query6);
 
     // Invoke the callout again.
-    ASSERT_NO_THROW(ha_impl.buffer6Receive(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->buffer6Receive(*callout_handle));
 
     // This time the callout should set the next step to SKIP to indicate to
     // the DHCP server that the message has been already parsed.
@@ -674,19 +713,19 @@ TEST_F(HAImplTest, subnet6Select) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -706,7 +745,7 @@ TEST_F(HAImplTest, subnet6Select) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // Make sure that the request was not dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -728,19 +767,19 @@ TEST_F(HAImplTest, subnet6SelectSharedNetwork) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -763,7 +802,7 @@ TEST_F(HAImplTest, subnet6SelectSharedNetwork) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // Make sure that the request was not dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -785,13 +824,13 @@ TEST_F(HAImplTest, subnet6SelectSingleRelationship) {
     ConstElementPtr ha_config = createValidJsonConfiguration(HAConfig::HOT_STANDBY);
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -809,7 +848,7 @@ TEST_F(HAImplTest, subnet6SelectSingleRelationship) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // The request should not be dropped and there should be no classes assigned
     // because the callout didn't call the HAService::inScope function.
@@ -823,19 +862,19 @@ TEST_F(HAImplTest, subnet6SelectDropNoServerName) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -852,7 +891,7 @@ TEST_F(HAImplTest, subnet6SelectDropNoServerName) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // The request should be dropped and no classes assigned to it.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -865,19 +904,19 @@ TEST_F(HAImplTest, subnet6SelectDropInvalidServerNameType) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // The hub is a standby server and by default serves no scopes. Explicitly
     // enable the failover scopes to make this server responsible for the
     // received packets.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -898,7 +937,7 @@ TEST_F(HAImplTest, subnet6SelectDropInvalidServerNameType) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // The request should be dropped and no classes assigned to it.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -911,18 +950,18 @@ TEST_F(HAImplTest, subnet6SelectDropNotInScope) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // This server serves server1/server2 scopes but not server3/server4 scopes.
     // The request should be dropped because the subnet will be associated with
     // the server3.
-    ha_impl.services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -943,7 +982,7 @@ TEST_F(HAImplTest, subnet6SelectDropNotInScope) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // The request should be dropped because the server is not responsible for
     // this scope currently.
@@ -959,16 +998,16 @@ TEST_F(HAImplTest, subnet6SelectNoSubnet) {
     ConstElementPtr ha_config = createValidHubJsonConfiguration();
 
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(ha_config));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(ha_config));
 
     // Starting the service is required before any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
-    ha_impl.services_->get("server2")->serveFailoverScopes();
-    ha_impl.services_->get("server4")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server2")->serveFailoverScopes();
+    test_ha_impl_->services_->get("server4")->serveFailoverScopes();
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -985,7 +1024,7 @@ TEST_F(HAImplTest, subnet6SelectNoSubnet) {
     callout_handle->setArgument("subnet6", subnet6);
 
     // Invoke the subnet6_select callout.
-    ASSERT_NO_THROW(ha_impl.subnet6Select(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->subnet6Select(*callout_handle));
 
     // No subnet has been selected and we have multiple relationships. We
     // expect that the server drops the packet.
@@ -998,18 +1037,18 @@ TEST_F(HAImplTest, subnet6SelectNoSubnet) {
 // Tests leases4_committed callout implementation.
 TEST_F(HAImplTest, leases4Committed) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // Make sure we wait for the acks from the backup server to be able to
     // test the case of sending lease updates even though the service is
     // in the state in which the lease updates are normally not sent.
-    ha_impl.config_->get()->setWaitBackupAck(true);
+    test_ha_impl_->config_->get()->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1038,7 +1077,7 @@ TEST_F(HAImplTest, leases4Committed) {
     HooksManager::park("leases4_committed", query4, []{});
 
     // There are no leases so the callout should return.
-    ASSERT_NO_THROW(ha_impl.leases4Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases4Committed(*callout_handle));
 
     // No updates are generated so the default status should not be modified.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -1053,27 +1092,27 @@ TEST_F(HAImplTest, leases4Committed) {
     leases4->push_back(lease4);
     callout_handle->setArgument("leases4", leases4);
 
-    ha_impl.config_->get()->setSendLeaseUpdates(false);
+    test_ha_impl_->config_->get()->setSendLeaseUpdates(false);
 
     // Park the packet.
     HooksManager::park("leases4_committed", query4, []{});
 
     // Run the callout again.
-    ASSERT_NO_THROW(ha_impl.leases4Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases4Committed(*callout_handle));
 
     // No updates are generated so the default status should not be modified.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
     EXPECT_TRUE(callout_handle->getParkingLotHandlePtr()->drop(query4));
 
     // Enable updates and retry.
-    ha_impl.config_->get()->setSendLeaseUpdates(true);
+    test_ha_impl_->config_->get()->setSendLeaseUpdates(true);
     callout_handle->setArgument("leases4", leases4);
 
     // Park the packet.
     HooksManager::park("leases4_committed", query4, []{});
 
     // Run the callout again.
-    ASSERT_NO_THROW(ha_impl.leases4Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases4Committed(*callout_handle));
 
     // This time the lease update should be generated and the status should
     // be set to "park".
@@ -1084,18 +1123,18 @@ TEST_F(HAImplTest, leases4Committed) {
 // Tests leases4_committed callout implementation for multiple relationships.
 TEST_F(HAImplTest, leases4CommittedMultipleRelationships) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // By enabling this setting we ensure that the lease updates are always
     // scheduled and the packet is parked because it is independent of a
     // server state.
-    ha_impl.config_->get("server2")->setWaitBackupAck(true);
+    test_ha_impl_->config_->get("server2")->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1128,7 +1167,7 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationships) {
     HooksManager::park("leases4_committed", query4, []{});
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.leases4Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases4Committed(*callout_handle));
 
     // Make sure the callout completed successfully. The "park" status means
     // there was no error during the callout.
@@ -1140,18 +1179,18 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationships) {
 // the relationship is not found.
 TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsNoServerName) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // By enabling this setting we ensure that the lease updates are always
     // scheduled and the packet is parked because it is independent of a
     // server state.
-    ha_impl.config_->get("server2")->setWaitBackupAck(true);
+    test_ha_impl_->config_->get("server2")->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1181,7 +1220,7 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsNoServerName) {
     HooksManager::park("leases4_committed", query4, []{});
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.leases4Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases4Committed(*callout_handle));
 
     // The relationship was not found so the packet should be dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -1192,18 +1231,18 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsNoServerName) {
 // the relationship name is invalid.
 TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsInvalidServerName) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // By enabling this setting we ensure that the lease updates are always
     // scheduled and the packet is parked because it is independent of a
     // server state.
-    ha_impl.config_->get("server2")->setWaitBackupAck(true);
+    test_ha_impl_->config_->get("server2")->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1236,7 +1275,7 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsInvalidServerName) {
     HooksManager::park("leases4_committed", query4, []{});
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.leases4Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases4Committed(*callout_handle));
 
     // The relationship was not found so the packet should be dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -1246,18 +1285,18 @@ TEST_F(HAImplTest, leases4CommittedMultipleRelationshipsInvalidServerName) {
 // Tests leases6_committed callout implementation.
 TEST_F(HAImplTest, leases6Committed) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // Make sure we wait for the acks from the backup server to be able to
     // test the case of sending lease updates even though the service is
     // in the state in which the lease updates are normally not sent.
-    ha_impl.config_->get()->setWaitBackupAck(true);
+    test_ha_impl_->config_->get()->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1286,7 +1325,7 @@ TEST_F(HAImplTest, leases6Committed) {
     HooksManager::park("leases6_committed", query6, []{});
 
     // There are no leases so the callout should return.
-    ASSERT_NO_THROW(ha_impl.leases6Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases6Committed(*callout_handle));
 
     // No updates are generated so the default status should not be modified.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -1300,27 +1339,27 @@ TEST_F(HAImplTest, leases6Committed) {
     leases6->push_back(lease6);
     callout_handle->setArgument("leases6", leases6);
 
-    ha_impl.config_->get()->setSendLeaseUpdates(false);
+    test_ha_impl_->config_->get()->setSendLeaseUpdates(false);
 
     // Park the packet.
     HooksManager::park("leases6_committed", query6, []{});
 
     // Run the callout again.
-    ASSERT_NO_THROW(ha_impl.leases6Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases6Committed(*callout_handle));
 
     // No updates are generated so the default status should not be modified.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
     EXPECT_TRUE(callout_handle->getParkingLotHandlePtr()->drop(query6));
 
     // Enable updates and retry.
-    ha_impl.config_->get()->setSendLeaseUpdates(true);
+    test_ha_impl_->config_->get()->setSendLeaseUpdates(true);
     callout_handle->setArgument("leases6", leases6);
 
     // Park the packet.
     HooksManager::park("leases6_committed", query6, []{});
 
     // Run the callout again.
-    ASSERT_NO_THROW(ha_impl.leases6Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases6Committed(*callout_handle));
 
     // This time the lease update should be generated and the status should
     // be set to "park".
@@ -1331,18 +1370,18 @@ TEST_F(HAImplTest, leases6Committed) {
 // Tests leases6_committed callout implementation for multiple relationships.
 TEST_F(HAImplTest, leases6CommittedMultipleRelationships) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // By enabling this setting we ensure that the lease updates are always
     // scheduled and the packet is parked because it is independent of a
     // server state.
-    ha_impl.config_->get("server2")->setWaitBackupAck(true);
+    test_ha_impl_->config_->get("server2")->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1374,7 +1413,7 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationships) {
     HooksManager::park("leases6_committed", query6, []{});
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.leases6Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases6Committed(*callout_handle));
 
     // Make sure the callout completed successfully. The "park" status means
     // there was no error during the callout.
@@ -1386,18 +1425,18 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationships) {
 // the relationship is not found.
 TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsNoServerName) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // By enabling this setting we ensure that the lease updates are always
     // scheduled and the packet is parked because it is independent of a
     // server state.
-    ha_impl.config_->get("server2")->setWaitBackupAck(true);
+    test_ha_impl_->config_->get("server2")->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1426,7 +1465,7 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsNoServerName) {
     HooksManager::park("leases6_committed", query6, []{});
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.leases6Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases6Committed(*callout_handle));
 
     // The relationship was not found so the packet should be dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -1437,18 +1476,18 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsNoServerName) {
 // the relationship name is invalid.
 TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsInvalidServerName) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required before running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv6));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv6));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv6));
 
     // By enabling this setting we ensure that the lease updates are always
     // scheduled and the packet is parked because it is independent of a
     // server state.
-    ha_impl.config_->get("server2")->setWaitBackupAck(true);
+    test_ha_impl_->config_->get("server2")->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -1480,7 +1519,7 @@ TEST_F(HAImplTest, leases6CommittedMultipleRelationshipsInvalidServerName) {
     HooksManager::park("leases6_committed", query6, []{});
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.leases6Committed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->leases6Committed(*callout_handle));
 
     // The relationship was not found so the packet should be dropped.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_DROP, callout_handle->getStatus());
@@ -1568,13 +1607,13 @@ TEST_F(HAImplTest, synchronizeHandler) {
 
 // Tests ha-continue command handler with a specified server name.
 TEST_F(HAImplTest, continueHandler) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON("{"
         "\"command\": \"ha-continue\","
@@ -1586,7 +1625,7 @@ TEST_F(HAImplTest, continueHandler) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.continueHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->continueHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -1597,20 +1636,20 @@ TEST_F(HAImplTest, continueHandler) {
 
 // Tests ha-continue command handler without a server name.
 TEST_F(HAImplTest, continueHandlerWithNoServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON("{ \"command\": \"ha-continue\" }");
 
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.continueHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->continueHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -1621,13 +1660,13 @@ TEST_F(HAImplTest, continueHandlerWithNoServerName) {
 
 // Tests ha-continue command handler with wrong server name.
 TEST_F(HAImplTest, continueHandlerWithWrongServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON("{"
         "\"command\": \"ha-continue\","
@@ -1639,7 +1678,7 @@ TEST_F(HAImplTest, continueHandlerWithWrongServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.continueHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->continueHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -1650,13 +1689,13 @@ TEST_F(HAImplTest, continueHandlerWithWrongServerName) {
 
 // Tests status-get command processed handler.
 TEST_F(HAImplTest, statusGet) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     std::string name = "status-get";
     ConstElementPtr response =
@@ -1667,7 +1706,7 @@ TEST_F(HAImplTest, statusGet) {
     callout_handle->setArgument("name", name);
     callout_handle->setArgument("response", response);
 
-    ASSERT_NO_THROW(ha_impl.commandProcessed(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->commandProcessed(*callout_handle));
 
     ConstElementPtr got;
     callout_handle->getArgument("response", got);
@@ -1711,14 +1750,14 @@ TEST_F(HAImplTest, statusGet) {
 
 // Tests status-get command processed handler for backup server.
 TEST_F(HAImplTest, statusGetBackupServer) {
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
-    ha_impl.config_->get()->setThisServerName("server3");
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
+    test_ha_impl_->config_->get()->setThisServerName("server3");
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     std::string name = "status-get";
     ConstElementPtr response =
@@ -1729,7 +1768,7 @@ TEST_F(HAImplTest, statusGetBackupServer) {
     callout_handle->setArgument("name", name);
     callout_handle->setArgument("response", response);
 
-    ASSERT_NO_THROW(ha_impl.commandProcessed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->commandProcessed(*callout_handle));
 
     ConstElementPtr got;
     callout_handle->getArgument("response", got);
@@ -1761,13 +1800,13 @@ TEST_F(HAImplTest, statusGetBackupServer) {
 // Tests status-get command processed handler for primary server being in the
 // passive-backup state.
 TEST_F(HAImplTest, statusGetPassiveBackup) {
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidPassiveBackupJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidPassiveBackupJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     std::string name = "status-get";
     ConstElementPtr response =
@@ -1778,7 +1817,7 @@ TEST_F(HAImplTest, statusGetPassiveBackup) {
     callout_handle->setArgument("name", name);
     callout_handle->setArgument("response", response);
 
-    ASSERT_NO_THROW(ha_impl.commandProcessed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->commandProcessed(*callout_handle));
 
     ConstElementPtr got;
     callout_handle->getArgument("response", got);
@@ -1810,13 +1849,13 @@ TEST_F(HAImplTest, statusGetPassiveBackup) {
 // Tests status-get command processed handler for standby server in the
 // hub-and-spoke mode.
 TEST_F(HAImplTest, statusGetHubAndSpoke) {
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidHubJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidHubJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     std::string name = "status-get";
     ConstElementPtr response =
@@ -1827,7 +1866,7 @@ TEST_F(HAImplTest, statusGetHubAndSpoke) {
     callout_handle->setArgument("name", name);
     callout_handle->setArgument("response", response);
 
-    ASSERT_NO_THROW(ha_impl.commandProcessed(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->commandProcessed(*callout_handle));
 
     ConstElementPtr got;
     callout_handle->getArgument("response", got);
@@ -1895,13 +1934,13 @@ TEST_F(HAImplTest, statusGetHubAndSpoke) {
 
 // Test ha-maintenance-notify command handler with server name.
 TEST_F(HAImplTest, maintenanceNotify) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -1916,7 +1955,7 @@ TEST_F(HAImplTest, maintenanceNotify) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.maintenanceNotifyHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->maintenanceNotifyHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -1927,13 +1966,13 @@ TEST_F(HAImplTest, maintenanceNotify) {
 
 // Test ha-maintenance-notify command handler without server name.
 TEST_F(HAImplTest, maintenanceNotifyNoServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -1947,7 +1986,7 @@ TEST_F(HAImplTest, maintenanceNotifyNoServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.maintenanceNotifyHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->maintenanceNotifyHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -1958,13 +1997,13 @@ TEST_F(HAImplTest, maintenanceNotifyNoServerName) {
 
 // Test ha-maintenance-notify command handler without server name.
 TEST_F(HAImplTest, maintenanceNotifyBadServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -1979,7 +2018,7 @@ TEST_F(HAImplTest, maintenanceNotifyBadServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.maintenanceNotifyHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->maintenanceNotifyHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -1988,16 +2027,15 @@ TEST_F(HAImplTest, maintenanceNotifyBadServerName) {
     checkAnswer(response, CONTROL_RESULT_ERROR, "server5 matches no configured 'server-name'");
 }
 
-
 // Test ha-reset command handler with a specified server name.
 TEST_F(HAImplTest, haReset) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2011,7 +2049,7 @@ TEST_F(HAImplTest, haReset) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.haResetHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->haResetHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2022,13 +2060,13 @@ TEST_F(HAImplTest, haReset) {
 
 // Test ha-reset command handler without a specified server name.
 TEST_F(HAImplTest, haResetNoServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2039,7 +2077,7 @@ TEST_F(HAImplTest, haResetNoServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.haResetHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->haResetHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2050,14 +2088,13 @@ TEST_F(HAImplTest, haResetNoServerName) {
 
 // Test ha-reset command handler with a wrong server name.
 TEST_F(HAImplTest, haResetBadServerName) {
-    HAImpl ha_impl;
-
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2071,7 +2108,7 @@ TEST_F(HAImplTest, haResetBadServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.haResetHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->haResetHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2082,13 +2119,13 @@ TEST_F(HAImplTest, haResetBadServerName) {
 
 // Test ha-heartbeat command handler with a specified server name.
 TEST_F(HAImplTest, haHeartbeat) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2102,7 +2139,7 @@ TEST_F(HAImplTest, haHeartbeat) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.heartbeatHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->heartbeatHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2113,13 +2150,13 @@ TEST_F(HAImplTest, haHeartbeat) {
 
 // Test ha-heartbeat command handler without a specified server name.
 TEST_F(HAImplTest, haHeartbeatNoServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2130,7 +2167,7 @@ TEST_F(HAImplTest, haHeartbeatNoServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.heartbeatHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->heartbeatHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2141,13 +2178,13 @@ TEST_F(HAImplTest, haHeartbeatNoServerName) {
 
 // Test ha-heartbeat command handler with a wrong server name.
 TEST_F(HAImplTest, haHeartbeatBadServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2161,7 +2198,7 @@ TEST_F(HAImplTest, haHeartbeatBadServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.heartbeatHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->heartbeatHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2172,13 +2209,13 @@ TEST_F(HAImplTest, haHeartbeatBadServerName) {
 
 // Test ha-sync-complete-notify command handler with a specified server name.
 TEST_F(HAImplTest, haSyncCompleteNotify) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2192,7 +2229,7 @@ TEST_F(HAImplTest, haSyncCompleteNotify) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.syncCompleteNotifyHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->syncCompleteNotifyHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2204,13 +2241,13 @@ TEST_F(HAImplTest, haSyncCompleteNotify) {
 
 // Test ha-sync-complete-notify command handler without a specified server name.
 TEST_F(HAImplTest, haSyncCompleteNotifyNoServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2221,7 +2258,7 @@ TEST_F(HAImplTest, haSyncCompleteNotifyNoServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.syncCompleteNotifyHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->syncCompleteNotifyHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2233,13 +2270,13 @@ TEST_F(HAImplTest, haSyncCompleteNotifyNoServerName) {
 
 // Test ha-sync-complete-notify command handler with a wrong server name.
 TEST_F(HAImplTest, haSyncCompleteNotifyBadServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2253,7 +2290,7 @@ TEST_F(HAImplTest, haSyncCompleteNotifyBadServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.syncCompleteNotifyHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->syncCompleteNotifyHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2264,13 +2301,13 @@ TEST_F(HAImplTest, haSyncCompleteNotifyBadServerName) {
 
 // Test ha-scopes command handler with a specified server name.
 TEST_F(HAImplTest, haScopes) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2285,7 +2322,7 @@ TEST_F(HAImplTest, haScopes) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.scopesHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->scopesHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2296,13 +2333,13 @@ TEST_F(HAImplTest, haScopes) {
 
 // Test ha-scopes command handler without a specified server name.
 TEST_F(HAImplTest, haScopesNoServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2316,7 +2353,7 @@ TEST_F(HAImplTest, haScopesNoServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.scopesHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->scopesHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2327,13 +2364,13 @@ TEST_F(HAImplTest, haScopesNoServerName) {
 
 // Test ha-scopes command handler with a wrong server name.
 TEST_F(HAImplTest, haScopesBadServerName) {
-    HAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    ha_impl_.reset(new HAImpl());
+    ASSERT_NO_THROW(ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(ha_impl_->startServices(io_service_, network_state,
+                                            HAServerType::DHCPv4));
 
     ConstElementPtr command = Element::fromJSON(
         "{"
@@ -2348,7 +2385,7 @@ TEST_F(HAImplTest, haScopesBadServerName) {
     CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
     callout_handle->setArgument("command", command);
 
-    ASSERT_NO_THROW(ha_impl.scopesHandler(*callout_handle));
+    ASSERT_NO_THROW(ha_impl_->scopesHandler(*callout_handle));
 
     ConstElementPtr response;
     callout_handle->getArgument("response", response);
@@ -2360,18 +2397,18 @@ TEST_F(HAImplTest, haScopesBadServerName) {
 // Tests lease4_server_decline callout implementation.
 TEST_F(HAImplTest, lease4ServerDecline) {
     // Create implementation object and configure it.
-    TestHAImpl ha_impl;
-    ASSERT_NO_THROW(ha_impl.configure(createValidJsonConfiguration()));
+    test_ha_impl_.reset(new TestHAImpl());
+    ASSERT_NO_THROW(test_ha_impl_->configure(createValidJsonConfiguration()));
 
     // Starting the service is required prior to running any callouts.
     NetworkStatePtr network_state(new NetworkState(NetworkState::DHCPv4));
-    ASSERT_NO_THROW(ha_impl.startServices(io_service_, network_state,
-                                          HAServerType::DHCPv4));
+    ASSERT_NO_THROW(test_ha_impl_->startServices(io_service_, network_state,
+                                                 HAServerType::DHCPv4));
 
     // Make sure we wait for the acks from the backup server to be able to
     // test the case of sending lease updates even though the service is
     // in the state in which the lease updates are normally not sent.
-    ha_impl.config_->get()->setWaitBackupAck(true);
+    test_ha_impl_->config_->get()->setWaitBackupAck(true);
 
     // Create callout handle to be used for passing arguments to the
     // callout.
@@ -2396,10 +2433,10 @@ TEST_F(HAImplTest, lease4ServerDecline) {
     // Set initial status.
     callout_handle->setStatus(CalloutHandle::NEXT_STEP_CONTINUE);
 
-    ha_impl.config_->get()->setSendLeaseUpdates(false);
+    test_ha_impl_->config_->get()->setSendLeaseUpdates(false);
 
     // Run the callout.
-    ASSERT_NO_THROW(ha_impl.lease4ServerDecline(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->lease4ServerDecline(*callout_handle));
 
     // Status should be continue.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
@@ -2409,11 +2446,11 @@ TEST_F(HAImplTest, lease4ServerDecline) {
     EXPECT_EQ(peers_to_update, 0);
 
     // Enable updates and retry.
-    ha_impl.config_->get()->setSendLeaseUpdates(true);
+    test_ha_impl_->config_->get()->setSendLeaseUpdates(true);
     callout_handle->setArgument("lease4", lease4);
 
     // Run the callout again.
-    ASSERT_NO_THROW(ha_impl.lease4ServerDecline(*callout_handle));
+    ASSERT_NO_THROW(test_ha_impl_->lease4ServerDecline(*callout_handle));
 
     // Status should be continue.
     EXPECT_EQ(CalloutHandle::NEXT_STEP_CONTINUE, callout_handle->getStatus());
index 2840f5806552b57bc9ecc4cdf45c5efac568a35c..e3278814a4cdad433f00e8230e1663037edbf7db 100644 (file)
@@ -626,7 +626,10 @@ public:
         listener2_->stop();
         listener3_->stop();
         io_service_->restart();
-        io_service_->poll();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
         MultiThreadingMgr::instance().setMode(false);
         CfgMgr::instance().clear();
     }
@@ -1509,6 +1512,12 @@ public:
         // Change the partner's response to success.
         factory2_->getResponseCreator()->setControlResult(CONTROL_RESULT_SUCCESS);
 
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+
         // Try sending the lease updates again. The previously rejected lease should
         // now be accepted and the counter should be 0.
         bool unpark_called = false;
@@ -2083,7 +2092,10 @@ public:
         io_service_->stop();
         thread->join();
         io_service_->restart();
-        io_service_->poll();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Runs HAService::processSynchronize for the DHCPv6 server
@@ -2133,7 +2145,10 @@ public:
         io_service_->stop();
         thread->join();
         io_service_->restart();
-        io_service_->poll();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
     }
 
     /// @brief Tests scenarios when a single lease update is sent to a partner while
@@ -4871,7 +4886,10 @@ TEST_F(HAServiceTest, processMaintenanceStartSuccess) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner of our server is online and should have responded with
     // the success status. Therefore, this server should have transitioned
@@ -4923,7 +4941,10 @@ TEST_F(HAServiceTest, processMaintenanceStartSuccessAuthorized) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner of our server is online and should have responded with
     // the success status. Therefore, this server should have transitioned
@@ -4966,7 +4987,10 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerDown) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner of our server is online and should have responded with
     // the success status. Therefore, this server should have transitioned
@@ -5010,7 +5034,10 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerError) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     ASSERT_TRUE(rsp);
     checkAnswer(rsp, CONTROL_RESULT_SUCCESS,
@@ -5052,7 +5079,10 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerUnauthorized) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     ASSERT_TRUE(rsp);
     checkAnswer(rsp, CONTROL_RESULT_SUCCESS,
@@ -5095,7 +5125,10 @@ TEST_F(HAServiceTest, processMaintenanceStartNotAllowed) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     ASSERT_TRUE(rsp);
     checkAnswer(rsp, CONTROL_RESULT_ERROR,
@@ -5139,7 +5172,10 @@ TEST_F(HAServiceTest, processMaintenanceCancelSuccess) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner of our server is online and should have responded with
     // the success status. Therefore, this server should have transitioned
@@ -5190,7 +5226,10 @@ TEST_F(HAServiceTest, processMaintenanceCancelSuccessAuthorized) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner of our server is online and should have responded with
     // the success status. Therefore, this server should have transitioned
@@ -5233,7 +5272,10 @@ TEST_F(HAServiceTest, processMaintenanceCancelPartnerError) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner should have responded with an error.
     ASSERT_TRUE(rsp);
@@ -5279,7 +5321,10 @@ TEST_F(HAServiceTest, processMaintenanceCancelPartnerUnauthorized) {
     io_service_->stop();
     thread->join();
     io_service_->restart();
-    io_service_->poll();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 
     // The partner should have responded with an error.
     ASSERT_TRUE(rsp);
@@ -5562,6 +5607,14 @@ public:
           partner_(new HAPartner(listener2_, factory2_)) {
     }
 
+    ~HAServiceStateMachineTest() {
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+    }
+
     /// @brief Creates common HA service instance from the provided configuration.
     ///
     /// The custom @c state_ object is created and it replaces the default
index b7c43fea49d837d6b708beae99fdcd6c13ebc064..ea0d78f995c5d1b1290683cc978ba2363a469155 100644 (file)
@@ -56,6 +56,14 @@ HATest::HATest()
 }
 
 HATest::~HATest() {
+    if (timer_) {
+        timer_->cancel();
+    }
+    io_service_->restart();
+    try {
+        io_service_->poll();
+    } catch (...) {
+    }
 }
 
 void
@@ -72,26 +80,32 @@ HATest::startHAService() {
 void
 HATest::runIOService(long ms) {
     io_service_->restart();
-    IntervalTimer timer(io_service_);
-    timer.setup(std::bind(&IOService::stop, io_service_), ms,
-                IntervalTimer::ONE_SHOT);
+    timer_.reset(new IntervalTimer(io_service_));
+    timer_->setup(std::bind(&IOService::stop, io_service_), ms,
+                 IntervalTimer::ONE_SHOT);
+
     io_service_->run();
-    timer.cancel();
+
+    timer_->cancel();
+    auto f = [](IntervalTimerPtr) {};
+    io_service_->post(std::bind(f, timer_));
 }
 
 void
 HATest::runIOService(long ms, std::function<bool()> stop_condition) {
     io_service_->restart();
-    IntervalTimer timer(io_service_);
+    timer_.reset(new IntervalTimer(io_service_));
     bool timeout = false;
-    timer.setup(std::bind(&HATest::stopIOServiceHandler, this, std::ref(timeout)),
-                ms, IntervalTimer::ONE_SHOT);
+    timer_->setup(std::bind(&HATest::stopIOServiceHandler, this, std::ref(timeout)),
+                  ms, IntervalTimer::ONE_SHOT);
 
     while (!stop_condition() && !timeout) {
         io_service_->runOne();
     }
 
-    timer.cancel();
+    timer_->cancel();
+    auto f = [](IntervalTimerPtr) {};
+    io_service_->post(std::bind(f, timer_));
 }
 
 boost::shared_ptr<std::thread>
index b001dc5e639547fdc76fbb9660e8678bcc1af67b..8f52190fc0532569029b1d4df6147c7f3b8b78f3 100644 (file)
@@ -309,6 +309,9 @@ public:
 
     /// @brief Object holding a state of the DHCP service.
     dhcp::NetworkStatePtr network_state_;
+
+    /// @brief Test timer.
+    isc::asiolink::IntervalTimerPtr timer_;
 };
 
 } // end of namespace isc::ha::test
index df8cf1856536bdadb461109c168cd3b01a02ce04..b0c3b46d1b108f8459aa0cc110d2b645387abbbc 100644 (file)
@@ -54,27 +54,26 @@ const int DBG_ALL = DBGLVL_TRACE_DETAIL + 20;
 /// as a coroutine and passed as callback to many async_*() functions) and we
 /// want keep the same data).  Organising the data in this way keeps copying to
 /// a minimum.
-struct IOFetchData {
-    IOServicePtr io_service_;                ///< The IO service
+struct IOFetchData : boost::noncopyable {
+    IOServicePtr                  io_service_;       ///< The IO service
     // The first two members are shared pointers to a base class because what is
     // actually instantiated depends on whether the fetch is over UDP or TCP,
     // which is not known until construction of the IOFetch.  Use of a shared
     // pointer here is merely to ensure deletion when the data object is deleted.
-    boost::scoped_ptr<IOAsioSocket<IOFetch>> socket;
-                                             ///< Socket to use for I/O
-    boost::scoped_ptr<IOEndpoint> remote_snd;///< Where the fetch is sent
-    boost::scoped_ptr<IOEndpoint> remote_rcv;///< Where the response came from
-    OutputBufferPtr   msgbuf;                ///< Wire buffer for question
-    OutputBufferPtr   received;              ///< Received data put here
-    IOFetch::Callback*          callback;    ///< Called on I/O Completion
-    boost::asio::deadline_timer timer;       ///< Timer to measure timeouts
-    IOFetch::Protocol           protocol;    ///< Protocol being used
-    size_t                      cumulative;  ///< Cumulative received amount
-    size_t                      expected;    ///< Expected amount of data
-    size_t                      offset;      ///< Offset to receive data
-    bool                        stopped;     ///< Have we stopped running?
-    int                         timeout;     ///< Timeout in ms
-    bool                        packet;      ///< true if packet was supplied
+    boost::scoped_ptr<IOAsioSocket<IOFetch>> socket; ///< Socket to use for I/O
+    boost::scoped_ptr<IOEndpoint> remote_snd;        ///< Where the fetch is sent
+    boost::scoped_ptr<IOEndpoint> remote_rcv;        ///< Where the response came from
+    OutputBufferPtr               msgbuf;            ///< Wire buffer for question
+    OutputBufferPtr               received;          ///< Received data put here
+    IOFetch::Callback*            callback;          ///< Called on I/O Completion
+    boost::asio::deadline_timer   timer;             ///< Timer to measure timeouts
+    IOFetch::Protocol             protocol;          ///< Protocol being used
+    size_t                        cumulative;        ///< Cumulative received amount
+    size_t                        expected;          ///< Expected amount of data
+    size_t                        offset;            ///< Offset to receive data
+    bool                          stopped;           ///< Have we stopped running?
+    int                           timeout;           ///< Timeout in ms
+    bool                          packet;            ///< true if packet was supplied
 
     // In case we need to log an error, the origin of the last asynchronous
     // I/O is recorded.  To save time and simplify the code, this is recorded
@@ -133,8 +132,13 @@ struct IOFetchData {
         packet(false),
         origin(ASIODNS_UNKNOWN_ORIGIN),
         staging(),
-        qid(QidGenerator::getInstance().generateQid())
-    {}
+        qid(QidGenerator::getInstance().generateQid()) {
+    }
+
+    /// \brief Destructor
+    ~IOFetchData() {
+        timer.cancel();
+    }
 
     // Checks if the response we received was ok;
     // - data contains the buffer we read, as well as the address
index 59bbe566b705b1698dae3d734ac33fc1705d79f9..1001807ccdb4f3531e1a34cb1897596fd0ad4622 100644 (file)
@@ -52,42 +52,42 @@ const size_t MAX_SIZE = 64 * 1024;  // Should be able to take 64kB
 const bool DEBUG = false;
 
 /// \brief Test fixture for the asiolink::IOFetch.
-class IOFetchTest : public virtual ::testing::Test, public virtual IOFetch::Callback
-{
+class IOFetchTest : public virtual ::testing::Test, public virtual IOFetch::Callback {
 public:
-    IOServicePtr    service_;       ///< Service to run the query
-    IOFetch::Result expected_;      ///< Expected result of the callback
-    bool            run_;           ///< Did the callback run already?
-    Question        question_;      ///< What to ask
-    OutputBufferPtr result_buff_;   ///< Buffer to hold result of fetch
-    OutputBufferPtr msgbuf_;        ///< Buffer corresponding to known question
-    IOFetch         udp_fetch_;     ///< For UDP query test
-    IOFetch         tcp_fetch_;     ///< For TCP query test
-    IOFetch::Protocol protocol_;    ///< Protocol being tested
-    size_t          cumulative_;    ///< Cumulative data received by "server".
-    deadline_timer  timer_;         ///< Timer to measure timeouts
+    IOServicePtr                     service_;                  ///< Service to run the query
+    IOFetch::Result                  expected_;                 ///< Expected result of the callback
+    bool                             run_;                      ///< Did the callback run already?
+    Question                         question_;                 ///< What to ask
+    OutputBufferPtr                  result_buff_;              ///< Buffer to hold result of fetch
+    OutputBufferPtr                  msgbuf_;                   ///< Buffer corresponding to known question
+    IOFetch                          udp_fetch_;                ///< For UDP query test
+    IOFetch                          tcp_fetch_;                ///< For TCP query test
+    IOFetch::Protocol                protocol_;                 ///< Protocol being tested
+    size_t                           cumulative_;               ///< Cumulative data received by "server".
+    deadline_timer                   timer_;                    ///< Timer to measure timeouts
 
     // The next member is the buffer in which the "server" (implemented by the
     // response handler methods in this class) receives the question sent by the
     // fetch object.
-    uint8_t         receive_buffer_[MAX_SIZE]; ///< Server receive buffer
-    OutputBufferPtr expected_buffer_;          ///< Data we expect to receive
-    vector<uint8_t> send_buffer_;           ///< Server send buffer
-    uint16_t        send_cumulative_;       ///< Data sent so far
+    uint8_t                          receive_buffer_[MAX_SIZE]; ///< Server receive buffer
+    OutputBufferPtr                  expected_buffer_;          ///< Data we expect to receive
+    vector<uint8_t>                  send_buffer_;              ///< Server send buffer
+    uint16_t                         send_cumulative_;          ///< Data sent so far
 
     // Other data.
-    string          return_data_;           ///< Data returned by server
-    string          test_data_;             ///< Large string - here for convenience
-    bool            debug_;                 ///< true to enable debug output
-    size_t          tcp_send_size_;         ///< Max size of TCP send
-    uint8_t         qid_0;                  ///< First octet of qid
-    uint8_t         qid_1;                  ///< Second octet of qid
-
-    bool            tcp_short_send_;        ///< If set to true, we do not send
-                                            ///  all data in the tcp response
-    boost::shared_ptr<udp::socket> udp_socket_;
-    boost::shared_ptr<tcp::socket> tcp_socket_;
+    string                           return_data_;              ///< Data returned by server
+    string                           test_data_;                ///< Large string - here for convenience
+    bool                             debug_;                    ///< true to enable debug output
+    size_t                           tcp_send_size_;            ///< Max size of TCP send
+    uint8_t                          qid_0;                     ///< First octet of qid
+    uint8_t                          qid_1;                     ///< Second octet of qid
+
+    bool                             tcp_short_send_;           ///< If set to true, we do not send
+                                                                ///  all data in the tcp response
+    boost::shared_ptr<udp::socket>   udp_socket_;
+    boost::shared_ptr<tcp::socket>   tcp_socket_;
     boost::shared_ptr<tcp::acceptor> tcp_acceptor_;
+    bool                             shutdown_;
 
     /// \brief Constructor
     IOFetchTest() :
@@ -115,8 +115,8 @@ public:
         tcp_send_size_(0),
         qid_0(0),
         qid_1(0),
-        tcp_short_send_(false)
-    {
+        tcp_short_send_(false),
+        shutdown_(false) {
         // Construct the data buffer for question we expect to receive.
         Message msg(Message::RENDER);
         msg.setQid(0);
@@ -153,6 +153,8 @@ public:
     }
 
     virtual ~IOFetchTest() {
+        shutdown_ = true;
+        timer_.cancel();
         service_->restart();
         try {
             service_->poll();
@@ -178,8 +180,10 @@ public:
     void udpReceiveHandler(udp::endpoint* remote, udp::socket* socket,
                            boost::system::error_code ec = boost::system::error_code(),
                            size_t length = 0, bool bad_qid = false,
-                           bool second_send = false)
-    {
+                           bool second_send = false) {
+        if (shutdown_) {
+            return;
+        }
         if (debug_) {
             cout << "udpReceiveHandler(): error = " << ec.value() <<
                     ", length = " << length << endl;
@@ -228,8 +232,10 @@ public:
     /// \param socket Socket on which data will be received
     /// \param ec Boost error code, value should be zero.
     void tcpAcceptHandler(tcp::socket* socket,
-                          boost::system::error_code ec = boost::system::error_code())
-    {
+                          boost::system::error_code ec = boost::system::error_code()) {
+        if (shutdown_) {
+            return;
+        }
         if (debug_) {
             cout << "tcpAcceptHandler(): error = " << ec.value() << endl;
         }
@@ -269,8 +275,10 @@ public:
     /// \param length Amount of data received.
     void tcpReceiveHandler(tcp::socket* socket,
                            boost::system::error_code ec = boost::system::error_code(),
-                           size_t length = 0)
-    {
+                           size_t length = 0) {
+        if (shutdown_) {
+            return;
+        }
         if (debug_) {
             cout << "tcpReceiveHandler(): error = " << ec.value() <<
                     ", length = " << length << endl;
@@ -337,6 +345,9 @@ public:
     ///
     /// \param socket Socket over which send should take place
     void tcpSendData(tcp::socket* socket) {
+        if (shutdown_) {
+            return;
+        }
         if (debug_) {
             cout << "tcpSendData()" << endl;
         }
@@ -402,8 +413,10 @@ public:
     /// \param length Number of bytes sent.
     void tcpSendHandler(size_t expected, tcp::socket* socket,
                         boost::system::error_code ec = boost::system::error_code(),
-                        size_t length = 0)
-    {
+                        size_t length = 0) {
+        if (shutdown_) {
+            return;
+        }
         if (debug_) {
             cout << "tcpSendHandler(): error = " << ec.value() <<
                     ", length = " << length << endl;
@@ -511,8 +524,8 @@ public:
 
         // Stop before it is started
         fetch.stop();
-        service_->post(fetch);
 
+        service_->post(fetch);
         service_->run();
         EXPECT_TRUE(run_);
     }
index 68c4e21b96730660958c8ef2153baa59c77cdeaa..9397088ec0bc7f1c4709cc38ffc5fe3b4668867f 100644 (file)
@@ -41,7 +41,7 @@ public:
     /// state post construction is STOPPED.  If false, the constructor will
     /// invoke run() to transition the pool into the RUNNING state.
     IoServiceThreadPool(asiolink::IOServicePtr io_service, size_t pool_size,
-                   bool defer_start = false);
+                        bool defer_start = false);
 
     /// @brief Destructor
     ///
index c2e70fcfe9c6083b51826911366ab9c3a96a6c59..44e83057a2bbb77482f0d98c5b5f594523006580 100644 (file)
@@ -258,8 +258,7 @@ private:
 
 template <typename C>
 TCPSocket<C>::TCPSocket(boost::asio::ip::tcp::socket& socket) :
-    socket_ptr_(), socket_(socket), send_buffer_()
-{
+    socket_ptr_(), socket_(socket), send_buffer_() {
 }
 
 // Constructor - create socket on the fly
@@ -267,15 +266,14 @@ TCPSocket<C>::TCPSocket(boost::asio::ip::tcp::socket& socket) :
 template <typename C>
 TCPSocket<C>::TCPSocket(const IOServicePtr& io_service) : io_service_(io_service),
     socket_ptr_(new boost::asio::ip::tcp::socket(io_service_->getInternalIOService())),
-    socket_(*socket_ptr_)
-{
+    socket_(*socket_ptr_) {
 }
 
 // Destructor.
 
 template <typename C>
-TCPSocket<C>::~TCPSocket()
-{
+TCPSocket<C>::~TCPSocket() {
+    close();
 }
 
 // Open the socket.
@@ -322,8 +320,7 @@ TCPSocket<C>::open(const IOEndpoint* endpoint, C& callback) {
 // an exception if this is the case.
 
 template <typename C> void
-TCPSocket<C>::asyncSend(const void* data, size_t length, C& callback)
-{
+TCPSocket<C>::asyncSend(const void* data, size_t length, C& callback) {
     if (socket_.is_open()) {
 
         try {
@@ -347,8 +344,7 @@ TCPSocket<C>::asyncSend(const void* data, size_t length, C& callback)
 
 template <typename C> void
 TCPSocket<C>::asyncSend(const void* data, size_t length,
-    const IOEndpoint*, C& callback)
-{
+    const IOEndpoint*, C& callback) {
     if (socket_.is_open()) {
 
         /// Need to copy the data into a temporary buffer and precede it with
@@ -382,8 +378,7 @@ TCPSocket<C>::asyncSend(const void* data, size_t length,
 // caller to initialize the data to zero
 template <typename C> void
 TCPSocket<C>::asyncReceive(void* data, size_t length, size_t offset,
-    IOEndpoint* endpoint, C& callback)
-{
+    IOEndpoint* endpoint, C& callback) {
     if (socket_.is_open()) {
         // Upconvert to a TCPEndpoint.  We need to do this because although
         // IOEndpoint is the base class of UDPEndpoint and TCPEndpoint, it
@@ -424,8 +419,7 @@ template <typename C> bool
 TCPSocket<C>::processReceivedData(const void* staging, size_t length,
                                   size_t& cumulative, size_t& offset,
                                   size_t& expected,
-                                  isc::util::OutputBufferPtr& outbuff)
-{
+                                  isc::util::OutputBufferPtr& outbuff) {
     // Point to the data in the staging buffer and note how much there is.
     const uint8_t* data = static_cast<const uint8_t*>(staging);
     size_t data_length = length;
index 179952d98fe3382f27b754cd6618dec3fc258a3e..13e32037f997fe06b233baaf874432e107245f82 100644 (file)
@@ -45,7 +45,7 @@ public:
     TLSSocket(const IOServicePtr& service, TlsContextPtr context);
 
     /// @brief Destructor.
-    virtual ~TLSSocket() { }
+    virtual ~TLSSocket();
 
     /// @brief Return file descriptor of underlying socket.
     virtual int getNative() const {
@@ -275,6 +275,13 @@ TLSSocket<C>::TLSSocket(const IOServicePtr& io_service, TlsContextPtr context)
       stream_(*stream_ptr_), socket_(stream_.lowest_layer()), send_buffer_() {
 }
 
+// Destructor.
+
+template <typename C>
+TLSSocket<C>::~TLSSocket() {
+    close();
+}
+
 // Open the socket.
 
 template <typename C> void
@@ -325,8 +332,7 @@ TLSSocket<C>::handshake(C& callback) {
 // an exception if this is the case.
 
 template <typename C> void
-TLSSocket<C>::asyncSend(const void* data, size_t length, C& callback)
-{
+TLSSocket<C>::asyncSend(const void* data, size_t length, C& callback) {
     if (!socket_.is_open()) {
         isc_throw(SocketNotOpen,
                   "attempt to send on a TLS socket that is not open");
@@ -349,8 +355,7 @@ TLSSocket<C>::asyncSend(const void* data, size_t length, C& callback)
 
 template <typename C> void
 TLSSocket<C>::asyncSend(const void* data, size_t length,
-                        const IOEndpoint*, C& callback)
-{
+                        const IOEndpoint*, C& callback) {
     if (!socket_.is_open()) {
         isc_throw(SocketNotOpen,
                   "attempt to send on a TLS socket that is not open");
@@ -384,8 +389,7 @@ TLSSocket<C>::asyncSend(const void* data, size_t length,
 // caller to initialize the data to zero
 template <typename C> void
 TLSSocket<C>::asyncReceive(void* data, size_t length, size_t offset,
-                           IOEndpoint* endpoint, C& callback)
-{
+                           IOEndpoint* endpoint, C& callback) {
     if (!socket_.is_open()) {
         isc_throw(SocketNotOpen,
                   "attempt to receive from a TLS socket that is not open");
@@ -427,8 +431,7 @@ template <typename C> bool
 TLSSocket<C>::processReceivedData(const void* staging, size_t length,
                                   size_t& cumulative, size_t& offset,
                                   size_t& expected,
-                                  isc::util::OutputBufferPtr& outbuff)
-{
+                                  isc::util::OutputBufferPtr& outbuff) {
     // Point to the data in the staging buffer and note how much there is.
     const uint8_t* data = static_cast<const uint8_t*>(staging);
     size_t data_length = length;
index 17afd2808537976d31300a3b0edc11fb87cbc7fb..bda7276fdc4213f8289dd1e2dec63aec93304f39 100644 (file)
@@ -168,8 +168,7 @@ private:
 
 template <typename C>
 UDPSocket<C>::UDPSocket(boost::asio::ip::udp::socket& socket) :
-    socket_ptr_(), socket_(socket), isopen_(true)
-{
+    socket_ptr_(), socket_(socket), isopen_(true) {
 }
 
 // Constructor - create socket on the fly
@@ -177,15 +176,14 @@ UDPSocket<C>::UDPSocket(boost::asio::ip::udp::socket& socket) :
 template <typename C>
 UDPSocket<C>::UDPSocket(const IOServicePtr& io_service) : io_service_(io_service),
     socket_ptr_(new boost::asio::ip::udp::socket(io_service_->getInternalIOService())),
-    socket_(*socket_ptr_), isopen_(false)
-{
+    socket_(*socket_ptr_), isopen_(false) {
 }
 
 // Destructor.
 
 template <typename C>
-UDPSocket<C>::~UDPSocket()
-{
+UDPSocket<C>::~UDPSocket() {
+    close();
 }
 
 // Open the socket.
@@ -228,8 +226,7 @@ UDPSocket<C>::open(const IOEndpoint* endpoint, C&) {
 
 template <typename C> void
 UDPSocket<C>::asyncSend(const void* data, size_t length,
-                        const IOEndpoint* endpoint, C& callback)
-{
+                        const IOEndpoint* endpoint, C& callback) {
     if (isopen_) {
 
         // Upconvert to a UDPEndpoint.  We need to do this because although
@@ -255,8 +252,7 @@ UDPSocket<C>::asyncSend(const void* data, size_t length,
 
 template <typename C> void
 UDPSocket<C>::asyncReceive(void* data, size_t length, size_t offset,
-                           IOEndpoint* endpoint, C& callback)
-{
+                           IOEndpoint* endpoint, C& callback) {
     if (isopen_) {
 
         // Upconvert the endpoint again.
@@ -286,8 +282,7 @@ template <typename C> bool
 UDPSocket<C>::processReceivedData(const void* staging, size_t length,
                                   size_t& cumulative, size_t& offset,
                                   size_t& expected,
-                                  isc::util::OutputBufferPtr& outbuff)
-{
+                                  isc::util::OutputBufferPtr& outbuff) {
     // Set return values to what we should expect.
     cumulative = length;
     expected = length;
index 66dc705e10b7fe2fbb736f0a5c1acf33f0e2eb56..c8fec0cd4efd97917f640a5fa72e5f987d248f5b 100644 (file)
@@ -81,14 +81,33 @@ CmdHttpListener::start() {
             .arg(port_)
             .arg(tls_context_ ? "true" : "false");
     } catch (const std::exception& ex) {
+        if (thread_pool_) {
+            // Stop the thread pool.
+            thread_pool_->stop();
+        }
+
+        if (http_listener_) {
+            // Stop the listener.
+            http_listener_->stop();
+        }
+
+        if (thread_io_service_) {
+            thread_io_service_->restart();
+            try {
+                thread_io_service_->poll();
+            } catch (...) {
+            }
+        }
+
+        // Get rid of the thread pool.
         thread_pool_.reset();
+
+        // Get rid of the listener.
         http_listener_.reset();
-        thread_io_service_->restart();
-        try {
-            thread_io_service_->poll();
-        } catch(...) {
-        }
+
+        // Ditch the IOService.
         thread_io_service_.reset();
+
         isc_throw(Unexpected, "CmdHttpListener::run failed: " << ex.what());
     }
 }
@@ -128,15 +147,21 @@ CmdHttpListener::stop() {
     // Stop the thread pool.
     thread_pool_->stop();
 
-    // Get rid of the listener.
-    http_listener_.reset();
+    // Stop the listener.
+    http_listener_->stop();
 
     thread_io_service_->restart();
     try {
         thread_io_service_->poll();
-    } catch(...) {
+    } catch (...) {
     }
 
+    // Get rid of the thread pool.
+    thread_pool_.reset();
+
+    // Get rid of the listener.
+    http_listener_.reset();
+
     // Ditch the IOService.
     thread_io_service_.reset();
 
index c08952979e22098c947d5a3c5275f95159952c1f..0abf6f2dd2835c30ce906566ac5ca06d68140b0a 100644 (file)
@@ -156,10 +156,10 @@ public:
     /// -# ncr_protocol is invalid, currently only NCR_UDP is supported
     /// -# ncr_format is invalid, currently only FMT_JSON is supported
     D2Params(const isc::asiolink::IOAddress& ip_address,
-                   const size_t port,
-                   const size_t dns_server_timeout,
-                   const dhcp_ddns::NameChangeProtocol& ncr_protocol,
-                   const dhcp_ddns::NameChangeFormat& ncr_format);
+             const size_t port,
+             const size_t dns_server_timeout,
+             const dhcp_ddns::NameChangeProtocol& ncr_protocol,
+             const dhcp_ddns::NameChangeFormat& ncr_format);
 
     /// @brief Default constructor
     /// The default constructor creates an instance that has updates disabled.
@@ -170,27 +170,27 @@ public:
 
     /// @brief Return the IP address D2 listens on.
     const isc::asiolink::IOAddress& getIpAddress() const {
-        return(ip_address_);
+        return (ip_address_);
     }
 
     /// @brief Return the TCP/UPD port D2 listens on.
     size_t getPort() const {
-        return(port_);
+        return (port_);
     }
 
     /// @brief Return the DNS server timeout value.
     size_t getDnsServerTimeout() const {
-        return(dns_server_timeout_);
+        return (dns_server_timeout_);
     }
 
     /// @brief Return the socket protocol in use.
     const dhcp_ddns::NameChangeProtocol& getNcrProtocol() const {
-         return(ncr_protocol_);
+         return (ncr_protocol_);
     }
 
     /// @brief Return the expected format of inbound requests (NCRs).
     const dhcp_ddns::NameChangeFormat& getNcrFormat() const {
-        return(ncr_format_);
+        return (ncr_format_);
     }
 
     /// @brief Return summary of the configuration used by D2.
index 4467577dc22b135ff83aa36d5434e05224665fb7..43236c3a24a3b7176f2e7d43f78084b7bd175aa7 100644 (file)
@@ -66,6 +66,12 @@ public:
     /// @brief TSIG key name for stats.
     std::string tsig_key_name_;
 
+    /// @brief Flag which indicates that the client has been stopped.
+    bool stopped_;
+
+    /// @brief The list of IOFetch objects.
+    std::list<IOFetchPtr> io_fetch_list_;
+
     /// @brief Constructor.
     ///
     /// @param response_placeholder Message object pointer which will be updated
@@ -119,13 +125,17 @@ public:
     /// @param update_key The flag indicating if the key statistics should also
     /// be updated.
     void incrStats(const std::string& stat, bool update_key = true);
+
+    /// @brief This function stops the IOFetch objects.
+    void stop();
 };
 
 DNSClientImpl::DNSClientImpl(D2UpdateMessagePtr& response_placeholder,
                              DNSClient::Callback* callback,
                              const DNSClient::Protocol proto)
     : in_buf_(new OutputBuffer(DEFAULT_BUFFER_SIZE)),
-      response_(response_placeholder), callback_(callback), proto_(proto) {
+      response_(response_placeholder), callback_(callback), proto_(proto),
+      stopped_(false) {
 
     // Response should be an empty pointer. It gets populated by the
     // operator() method.
@@ -158,11 +168,21 @@ DNSClientImpl::DNSClientImpl(D2UpdateMessagePtr& response_placeholder,
     }
 }
 
+void DNSClientImpl::stop() {
+    stopped_ = true;
+    for (auto const& io_fetch : io_fetch_list_) {
+        io_fetch->stop();
+    }
+}
+
 DNSClientImpl::~DNSClientImpl() {
 }
 
 void
 DNSClientImpl::operator()(asiodns::IOFetch::Result result) {
+    if (stopped_) {
+        return;
+    }
     // Get the status from IO. If no success, we just call user's callback
     // and pass the status code.
     DNSClient::Status status = getStatus(result);
@@ -228,6 +248,9 @@ DNSClientImpl::doUpdate(const asiolink::IOServicePtr& io_service,
                         D2UpdateMessage& update,
                         const unsigned int wait,
                         const D2TsigKeyPtr& tsig_key) {
+    if (stopped_) {
+        return;
+    }
     // The underlying implementation which we use to send DNS Updates uses
     // signed integers for timeout. If we want to avoid overflows we need to
     // respect this limitation here.
@@ -270,12 +293,13 @@ DNSClientImpl::doUpdate(const asiolink::IOServicePtr& io_service,
     // Timeout value is explicitly cast to the int type to avoid warnings about
     // overflows when doing implicit cast. It should have been checked by the
     // caller that the unsigned timeout value will fit into int.
-    IOFetch io_fetch(IOFetch::UDP, io_service, msg_buf, ns_addr, ns_port,
-                     in_buf_, this, static_cast<int>(wait));
+    IOFetchPtr io_fetch(new IOFetch(IOFetch::UDP, io_service, msg_buf, ns_addr, ns_port,
+                                    in_buf_, this, static_cast<int>(wait)));
+    io_fetch_list_.push_back(io_fetch);
 
     // Post the task to the task queue in the IO service. Caller will actually
     // run these tasks by executing IOService::run.
-    io_service->post(io_fetch);
+    io_service->post(*io_fetch);
 
     // Update sent statistics.
     incrStats("update-sent");
@@ -302,6 +326,12 @@ DNSClient::DNSClient(D2UpdateMessagePtr& response_placeholder,
 }
 
 DNSClient::~DNSClient() {
+    stop();
+}
+
+void
+DNSClient::stop() {
+    impl_->stop();
 }
 
 unsigned int
index 63a2c5c16ac8492f70ec6fe834d2c3a63f6e5eec..e736d4d9d5b78f36c1abb6025dd1b1b286892986 100644 (file)
@@ -96,6 +96,9 @@ public:
     /// @brief Virtual destructor, does nothing.
     ~DNSClient();
 
+    /// @brief Stop the client.
+    void stop();
+
     ///
     /// @name Copy constructor and assignment operator
     ///
index edfd3fdaa7769f68a2d9ca57d897caba5941cf78..bb13726bca6513a6512afdb5666f59ba6dcbea8b 100644 (file)
@@ -103,7 +103,7 @@ NameChangeTransaction(asiolink::IOServicePtr& io_service,
     }
 }
 
-NameChangeTransaction::~NameChangeTransaction(){
+NameChangeTransaction::~NameChangeTransaction() {
 }
 
 void
index 4ec19cd4849b295332fe62be00392ba30b429c2f..4209bae64266a28ae50e9f58e500ccc786cab541 100644 (file)
@@ -126,6 +126,7 @@ public:
     /// Sets the asiodns logging level back to DEBUG.
     virtual ~DNSClientTest() {
         test_timer_.cancel();
+        dns_client_->stop();
         service_->restart();
         try {
             service_->poll();
@@ -320,17 +321,18 @@ public:
     void runInvalidTimeoutTest() {
         expect_response_ = false;
 
-        // Create inbound message. Simply set the required message fields:
+        // Create outbound message. Simply set the required message fields:
         // error code and Zone section. This is enough to create on-wire format
         // of this message and send it.
-        D2UpdateMessage message(D2UpdateMessage::INBOUND);
+        D2UpdateMessage message(D2UpdateMessage::OUTBOUND);
+        ASSERT_NO_THROW(message.setRcode(Rcode(Rcode::NOERROR_CODE)));
+        ASSERT_NO_THROW(message.setZone(Name("example.com"), RRClass::IN()));
 
         // Start with a valid timeout equal to maximal allowed. This way we will
         // ensure that doUpdate doesn't throw an exception for valid timeouts.
         unsigned int timeout = DNSClient::getMaxTimeout();
-        EXPECT_THROW(dns_client_->doUpdate(service_, IOAddress(TEST_ADDRESS),
-                                           TEST_PORT, message, timeout),
-                     isc::d2::InvalidZoneSection);
+        EXPECT_NO_THROW(dns_client_->doUpdate(service_, IOAddress(TEST_ADDRESS),
+                                              TEST_PORT, message, timeout));
 
         // Cross the limit and expect that exception is thrown this time.
         timeout = DNSClient::getMaxTimeout() + 1;
index 1aceb6acbc4c85c474d61441981aef92515821aa..c9b8a671d842eb85ccc29a464c2a587937eec26a 100644 (file)
@@ -59,7 +59,7 @@ FauxServer::FauxServer(asiolink::IOServicePtr& io_service,
                        asiolink::IOAddress& address, size_t port)
     : io_service_(io_service), address_(address), port_(port),
       server_socket_(), receive_pending_(false), perpetual_receive_(true),
-      tsig_key_() {
+      tsig_key_(), stopped_(false) {
 
     server_socket_.reset(new boost::asio::ip::udp::socket(io_service_->getInternalIOService(),
                                                           boost::asio::ip::udp::v4()));
@@ -73,7 +73,7 @@ FauxServer::FauxServer(asiolink::IOServicePtr& io_service,
                        DnsServerInfo& server)
     : io_service_(io_service), address_(server.getIpAddress()),
       port_(server.getPort()), server_socket_(), receive_pending_(false),
-      perpetual_receive_(true), tsig_key_() {
+      perpetual_receive_(true), tsig_key_(), stopped_(false) {
     server_socket_.reset(new boost::asio::ip::udp::socket(io_service_->getInternalIOService(),
                                                           boost::asio::ip::udp::v4()));
     server_socket_->set_option(boost::asio::socket_base::reuse_address(true));
@@ -82,11 +82,17 @@ FauxServer::FauxServer(asiolink::IOServicePtr& io_service,
 }
 
 FauxServer::~FauxServer() {
+    stop();
+}
+
+void FauxServer::stop() {
+    stopped_ = true;
+    server_socket_->close();
 }
 
 void
-FauxServer::receive (const ResponseMode& response_mode,
-                     const dns::Rcode& response_rcode) {
+FauxServer::receive(const ResponseMode& response_mode,
+                    const dns::Rcode& response_rcode) {
     if (receive_pending_) {
         return;
     }
@@ -106,6 +112,9 @@ FauxServer::requestHandler(const boost::system::error_code& error,
                            std::size_t bytes_recvd,
                            const ResponseMode& response_mode,
                            const dns::Rcode& response_rcode) {
+    if (stopped_) {
+        return;
+    }
     receive_pending_ = false;
     // If we encountered an error or received no data then fail.
     // We expect the client to send good requests.
index cb309957472b86ce0d59924a994c818ab441a364..e89bc5a0e5b1970074fe7deeca2664125d218348 100644 (file)
@@ -72,6 +72,9 @@ public:
     /// NULL TSIG is not used.
     D2TsigKeyPtr tsig_key_;
 
+    /// @brief Flag which indicated that the server has been stopped.
+    bool stopped_;
+
     /// @brief Constructor
     ///
     /// @param io_service IOService to be used for socket IO.
@@ -90,6 +93,9 @@ public:
     /// @brief Destructor
     virtual ~FauxServer();
 
+    /// @brief Stop the server
+    void stop();
+
     /// @brief Initiates an asynchronous receive
     ///
     /// Starts the server listening for requests.  Upon completion of the
index 1179c74adb2a5ca7e48a924391aaf7d88fb0813d..48f220f0526fb67bafe6481de2d39ccb1e144373 100644 (file)
@@ -51,8 +51,7 @@ std::string ncrProtocolToString(NameChangeProtocol protocol) {
 
 //************************** NameChangeListener ***************************
 
-NameChangeListener::NameChangeListener(RequestReceiveHandler&
-                                       recv_handler)
+NameChangeListener::NameChangeListener(RequestReceiveHandler& recv_handler)
     : listening_(false), io_pending_(false), recv_handler_(recv_handler) {
 };
 
index 54633df6250066f22e219d06254e7d6501857f16..db6000c702c127cba2f88e106eb4dd0dc948ba63 100644 (file)
@@ -194,8 +194,8 @@ public:
         /// wise.
         ///
         /// @throw This method MUST NOT throw.
-        virtual void operator ()(const Result result,
-                                 NameChangeRequestPtr& ncr) = 0;
+        virtual void operator()(const Result result,
+                                NameChangeRequestPtr& ncr) = 0;
 
         virtual ~RequestReceiveHandler() {
         }
index f32404cb54b7faf404b46054ebe18cb535d868f9..c6ca025db8cf21d646988c6b8722d54667c6068b 100644 (file)
@@ -61,7 +61,6 @@ UDPCallback::putData(const uint8_t* src, size_t len) {
     data_->put_len_ = len;
 }
 
-
 //*************************** NameChangeUDPListener ***********************
 NameChangeUDPListener::
 NameChangeUDPListener(const isc::asiolink::IOAddress& ip_address,
@@ -116,7 +115,6 @@ NameChangeUDPListener::open(const isc::asiolink::IOServicePtr& io_service) {
     socket_.reset(new NameChangeUDPSocket(*asio_socket_));
 }
 
-
 void
 NameChangeUDPListener::doReceive() {
     // Call the socket's asynchronous receiving, passing ourself in as callback.
@@ -149,6 +147,9 @@ NameChangeUDPListener::close() {
         asio_socket_.reset();
     }
 
+    if (socket_) {
+        socket_->close();
+    }
     socket_.reset();
     io_service_.reset();
 }
@@ -200,7 +201,6 @@ NameChangeUDPListener::receiveCompletionHandler(const bool successful,
     invokeRecvHandler(result, ncr);
 }
 
-
 //*************************** NameChangeUDPSender ***********************
 
 NameChangeUDPSender::
@@ -292,6 +292,9 @@ NameChangeUDPSender::close() {
         asio_socket_.reset();
     }
 
+    if (socket_) {
+        socket_->close();
+    }
     socket_.reset();
 
     closeWatchSocket();
index ea074ba6724a4f3882b83e34e3d579896f1a94a7..84036533cec38d6cca94a40c6a07cc73a8d38e4a 100644 (file)
@@ -213,8 +213,7 @@ public:
         // Note this uses a synchronous send so it ships immediately.
         // If listener isn't in listening mode, it will get missed.
         udp_socket.send_to(boost::asio::buffer(ncr_buffer.getData(),
-                                     ncr_buffer.getLength()),
-                            listener_endpoint);
+                           ncr_buffer.getLength()), listener_endpoint);
     }
 
     /// @brief RequestReceiveHandler operator implementation for receiving NCRs.
index bca014b60e673c68e57a0557ef5453b491f86b60..89d6790204020cfaf02e674c722222aa3e5ca3b0 100644 (file)
@@ -164,6 +164,12 @@ public:
             setExtendedInfoSanityCheck(CfgConsistency::EXTENDED_INFO_CHECK_FIX);
         // Disable multi-threading.
         MultiThreadingMgr::instance().setMode(false);
+
+        getIOService()->restart();
+        try {
+            getIOService()->poll();
+        } catch(...) {
+        }
     }
 
     /// @brief Remove files being products of Lease File Cleanup.
index 66ab6490e067c2c7e08c80e09a644dab4b8ce6f5..853e7a2131efd16543823cdd1bfe70352fa7bec4 100644 (file)
@@ -402,6 +402,9 @@ private:
     /// after invocation. Defaults to false.
     void closeCallback(const bool clear = false);
 
+    /// @brief A reference to the IOService that drives socket IO.
+    IOServicePtr io_service_;
+
     /// @brief Pointer to the connection pool owning this connection.
     ///
     /// This is a weak pointer to avoid circular dependency between the
@@ -415,13 +418,13 @@ private:
     TlsContextPtr tls_context_;
 
     /// @brief TCP socket to be used for this connection.
-    std::unique_ptr<TCPSocket<SocketCallback> > tcp_socket_;
+    std::shared_ptr<TCPSocket<SocketCallback>> tcp_socket_;
 
     /// @brief TLS socket to be used for this connection.
-    std::unique_ptr<TLSSocket<SocketCallback> > tls_socket_;
+    std::shared_ptr<TLSSocket<SocketCallback>> tls_socket_;
 
     /// @brief Interval timer used for detecting request timeouts.
-    IntervalTimer timer_;
+    IntervalTimerPtr timer_;
 
     /// @brief Holds currently sent request.
     HttpRequestPtr current_request_;
@@ -1105,7 +1108,7 @@ private:
         }
     }
 
-    /// @brief A reference to the IOService that drives socket IO.
+    /// @brief A pointer to the IOService that drives socket IO.
     IOServicePtr io_service_;
 
     /// @brief Map of Destinations by URL and TLS context.
@@ -1122,12 +1125,12 @@ Connection::Connection(const IOServicePtr& io_service,
                        const TlsContextPtr& tls_context,
                        const ConnectionPoolPtr& conn_pool,
                        const Url& url)
-    : conn_pool_(conn_pool), url_(url), tls_context_(tls_context),
-      tcp_socket_(), tls_socket_(), timer_(io_service),
-      current_request_(), current_response_(), parser_(),
-      current_callback_(), buf_(), input_buf_(), current_transid_(0),
-      close_callback_(), started_(false), need_handshake_(false),
-      closed_(false) {
+    : io_service_(io_service), conn_pool_(conn_pool), url_(url),
+      tls_context_(tls_context), tcp_socket_(), tls_socket_(),
+      timer_(new IntervalTimer(io_service)), current_request_(),
+      current_response_(), parser_(), current_callback_(), buf_(), input_buf_(),
+      current_transid_(0), close_callback_(), started_(false),
+      need_handshake_(false), closed_(false) {
     if (!tls_context) {
         tcp_socket_.reset(new asiolink::TCPSocket<SocketCallback>(io_service));
     } else {
@@ -1316,7 +1319,7 @@ Connection::closeInternal() {
     closeCallback(true);
 
     closed_ = true;
-    timer_.cancel();
+    timer_->cancel();
     if (tcp_socket_) {
         tcp_socket_->close();
     }
@@ -1324,6 +1327,10 @@ Connection::closeInternal() {
         tls_socket_->close();
     }
 
+    auto f = [](IntervalTimerPtr, std::shared_ptr<TCPSocket<SocketCallback>>,
+                std::shared_ptr<TLSSocket<SocketCallback>>) {};
+    io_service_->post(std::bind(f, timer_, tcp_socket_, tls_socket_));
+
     resetState();
 }
 
@@ -1384,7 +1391,7 @@ Connection::terminateInternal(const boost::system::error_code& ec,
     HttpResponsePtr response;
     if (isTransactionOngoing()) {
 
-        timer_.cancel();
+        timer_->cancel();
         if (tcp_socket_) {
             tcp_socket_->cancel();
         }
@@ -1461,8 +1468,8 @@ Connection::terminateInternal(const boost::system::error_code& ec,
 void
 Connection::scheduleTimer(const long request_timeout) {
     if (request_timeout > 0) {
-        timer_.setup(std::bind(&Connection::timerCallback, this), request_timeout,
-                     IntervalTimer::ONE_SHOT);
+        timer_->setup(std::bind(&Connection::timerCallback, this), request_timeout,
+                      IntervalTimer::ONE_SHOT);
     }
 }
 
@@ -1649,7 +1656,7 @@ Connection::sendCallback(const uint64_t transid,
     }
 
     // Sending is in progress, so push back the timeout.
-    scheduleTimer(timer_.getInterval());
+    scheduleTimer(timer_->getInterval());
 
     // If any data have been sent, remove it from the buffer and only leave the
     // portion that still has to be sent.
@@ -1695,7 +1702,7 @@ Connection::receiveCallback(const uint64_t transid,
     }
 
     // Receiving is in progress, so push back the timeout.
-    scheduleTimer(timer_.getInterval());
+    scheduleTimer(timer_->getInterval());
 
     if (runParser(ec, length)) {
         doReceive(transid);
index a9110bceaf0d839f5c57e2a66efa624772008836..9c86b5558ff80b1881bf3e67ec73da8f93b119a5 100644 (file)
@@ -75,4 +75,3 @@ protected:
 }
 
 #endif
-
index 059845b06dba402e01c2ea49de2337715c944d84..c9634042811ff45e3683d7fd761f5cb0184a9c3a 100644 (file)
@@ -1027,7 +1027,11 @@ public:
         listener_.stop();
         listener2_.stop();
         listener3_.stop();
-        io_service_->poll();
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch(...) {
+        }
         MultiThreadingMgr::instance().setMode(false);
     }
 
index b1661db286f86a286f8f44927ce71cf4b82f5332..1b9276df8237a6936e5368b37a6eb7df158d7d01 100644 (file)
@@ -50,7 +50,7 @@ DControllerBase::setController(const DControllerBasePtr& controller) {
     if (controller_) {
         // This shouldn't happen, but let's make sure it can't be done.
         // It represents a programmatic error.
-        isc_throw (DControllerBaseError, "Multiple controller instances attempted.");
+        isc_throw(DControllerBaseError, "Multiple controller instances attempted.");
     }
 
     controller_ = controller;
@@ -103,7 +103,7 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
     } catch (const std::exception& ex) {
         LOG_FATAL(dctl_logger, DCTL_CONFIG_FILE_LOAD_FAIL)
             .arg(app_name_).arg(ex.what());
-        isc_throw (LaunchError, "Launch Failed: " << ex.what());
+        isc_throw(LaunchError, "Launch Failed: " << ex.what());
     }
 
     try {
@@ -111,11 +111,11 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
     } catch (const DaemonPIDExists& ex) {
         LOG_FATAL(dctl_logger, DCTL_ALREADY_RUNNING)
                   .arg(bin_name_).arg(ex.what());
-        isc_throw (LaunchError, "Launch Failed: " << ex.what());
+        isc_throw(LaunchError, "Launch Failed: " << ex.what());
     } catch (const std::exception& ex) {
         LOG_FATAL(dctl_logger, DCTL_PID_FILE_ERROR)
                   .arg(app_name_).arg(ex.what());
-        isc_throw (LaunchError, "Launch failed: " << ex.what());
+        isc_throw(LaunchError, "Launch failed: " << ex.what());
     }
 
     // Log the starting of the service.
@@ -134,8 +134,8 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
     } catch (const std::exception& ex) {
         LOG_FATAL(dctl_logger, DCTL_INIT_PROCESS_FAIL)
                   .arg(app_name_).arg(ex.what());
-        isc_throw (ProcessInitError,
-                   "Application Process initialization failed: " << ex.what());
+        isc_throw(ProcessInitError,
+                  "Application Process initialization failed: " << ex.what());
     }
 
     LOG_DEBUG(dctl_logger, isc::log::DBGLVL_START_SHUT, DCTL_STANDALONE)
@@ -147,8 +147,8 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
     if (rcode != 0) {
         LOG_FATAL(dctl_logger, DCTL_CONFIG_FILE_LOAD_FAIL)
                   .arg(app_name_).arg(comment->stringValue());
-        isc_throw (ProcessInitError, "Could Not load configuration file: "
-                   << comment->stringValue());
+        isc_throw(ProcessInitError, "Could Not load configuration file: "
+                  << comment->stringValue());
     }
 
     // Note that the controller was started.
@@ -163,8 +163,8 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
     } catch (const std::exception& ex) {
         LOG_FATAL(dctl_logger, DCTL_PROCESS_FAILED)
                   .arg(app_name_).arg(ex.what());
-        isc_throw (ProcessRunError,
-                   "Application process event loop failed: " << ex.what());
+        isc_throw(ProcessRunError,
+                  "Application process event loop failed: " << ex.what());
     }
 
     // All done, so bail out.
@@ -315,7 +315,7 @@ DControllerBase::parseArgs(int argc, char* argv[]) {
 
                 // We hit an invalid option.
                 isc_throw(InvalidUsage, "unsupported option: -" << saved_optopt <<
-                        (saved_optarg.empty() ? std::string() : " " + saved_optarg));
+                          (saved_optarg.empty() ? std::string() : " " + saved_optarg));
             }
             break;
         }
@@ -342,8 +342,8 @@ DControllerBase::initProcess() {
     try {
         process_.reset(createProcess());
     } catch (const std::exception& ex) {
-        isc_throw(DControllerBaseError, std::string("createProcess failed: ")
-                  ex.what());
+        isc_throw(DControllerBaseError, std::string("createProcess failed: ") +
+                  ex.what());
     }
 
     // This is pretty unlikely, but will test for it just to be safe..
@@ -733,7 +733,7 @@ DControllerBase::shutdownHandler(const std::string&, ConstElementPtr args) {
         }
 
         ConstElementPtr param = args->get("exit-value");
-        if (param)  {
+        if (param) {
             if (param->getType() != Element::integer) {
                 return (createAnswer(CONTROL_RESULT_ERROR,
                                      "parameter 'exit-value' is not an integer"));
@@ -813,7 +813,7 @@ DControllerBase::usage(const std::string & text) {
         std::cerr << "Usage error: " << text << std::endl;
     }
 
-    std::cerr << "Usage: " << bin_name_ <<  std::endl
+    std::cerr << "Usage: " << bin_name_ << std::endl
               << "  -v: print version number and exit" << std::endl
               << "  -V: print extended version information and exit"
               << std::endl
index 0c382d293496d816b40fa43e8d8c5a988cbefbf4..0bbefda958ac43e77233feeeaffc15bf97e79c16 100644 (file)
@@ -135,8 +135,8 @@ public:
     /// in their main function. Such a logger uses environmental variables to
     /// control severity, verbosity etc.
     ///
-    /// @param argc  is the number of command line arguments supplied
-    /// @param argv  is the array of string (char *) command line arguments
+    /// @param argc is the number of command line arguments supplied
+    /// @param argv is the array of string (char *) command line arguments
     /// @param test_mode is a bool value which indicates if
     /// @c DControllerBase::launch should be run in the test mode (if true).
     /// This parameter doesn't have default value to force test implementers to
@@ -144,7 +144,7 @@ public:
     ///
     /// @throw throws one of the following exceptions:
     /// InvalidUsage - Indicates invalid command line.
-    /// ProcessInitError  - Failed to create and initialize application
+    /// ProcessInitError - Failed to create and initialize application
     /// process object.
     /// ProcessRunError - A fatal error occurred while in the application
     /// process event loop.
@@ -157,7 +157,7 @@ public:
     /// implementation will merge the configuration update into the existing
     /// configuration and then invoke the application process' configure method.
     ///
-    /// @param  new_config is the new configuration
+    /// @param new_config is the new configuration
     ///
     /// @return returns an Element that contains the results of configuration
     /// update composed of an integer status value (0 means successful,
@@ -172,7 +172,7 @@ public:
     /// configuration and then invoke the application process' configure method
     /// with a final rollback.
     ///
-    /// @param  new_config is the new configuration
+    /// @param new_config is the new configuration
     ///
     /// @return returns an Element that contains the results of configuration
     /// update composed of an integer status value (0 means successful,
@@ -495,8 +495,8 @@ protected:
     /// -c/t for specifying the configuration file, -d for verbose logging,
     /// and -v/V/W for version reports.
     ///
-    /// @param argc  is the number of command line arguments supplied
-    /// @param argv  is the array of string (char *) command line arguments
+    /// @param argc is the number of command line arguments supplied
+    /// @param argv is the array of string (char *) command line arguments
     ///
     /// @throw InvalidUsage when there are usage errors.
     /// @throw VersionMessage if the -v, -V or -W arguments is given.
index 24eaff04692ea16842a78a42fe83b95ba96b32f3..f60e299b70872ba5972f2b809dda1deb4c89f8f5 100644 (file)
@@ -145,7 +145,13 @@ public:
               bool check_only = false) = 0;
 
     /// @brief Destructor
-    virtual ~DProcessBase(){};
+    virtual ~DProcessBase() {
+        io_service_->restart();
+        try {
+            io_service_->poll();
+        } catch (...) {
+        }
+    }
 
     /// @brief Checks if the process has been instructed to shut down.
     ///
index 6bdc83d202a09449d55eabec6e17f3ec0b3ede56..54b38b0d647dba85918977535b3f77dfd6b75c5d 100644 (file)
@@ -28,10 +28,9 @@ MtTcpListenerMgr::MtTcpListenerMgr(TcpListenerFactory listener_factory,
                                    const uint16_t thread_pool_size /* = 1 */,
                                    TlsContextPtr context /* = () */,
                                    TcpConnectionFilterCallback connection_filter /* = 0 */)
-    : listener_factory_(listener_factory),
-      address_(address), port_(port), thread_io_service_(), tcp_listener_(),
-      thread_pool_size_(thread_pool_size), thread_pool_(),
-      tls_context_(context), connection_filter_(connection_filter),
+    : listener_factory_(listener_factory), address_(address), port_(port),
+      thread_io_service_(), tcp_listener_(), thread_pool_size_(thread_pool_size),
+      thread_pool_(), tls_context_(context), connection_filter_(connection_filter),
       idle_timeout_(TCP_IDLE_CONNECTION_TIMEOUT) {
 }
 
@@ -78,14 +77,33 @@ MtTcpListenerMgr::start() {
             .arg(port_)
             .arg(tls_context_ ? "true" : "false");
     } catch (const std::exception& ex) {
-        tcp_listener_.reset();
-        thread_pool_.reset();
-        thread_io_service_->restart();
-        try {
-            thread_io_service_->poll();
-        } catch (...) {
+        if (thread_pool_) {
+            // Stop the thread pool.
+            thread_pool_->stop();
         }
+
+        if (tcp_listener_) {
+            // Stop the listener.
+            tcp_listener_->stop();
+        }
+
+        if (thread_io_service_) {
+            thread_io_service_->restart();
+            try {
+                thread_io_service_->poll();
+            } catch (...) {
+            }
+        }
+
+        // Get rid of the thread pool.
+        thread_pool_.reset();
+
+        // Get rid of the listener.
+        tcp_listener_.reset();
+
+        // Ditch the IOService.
         thread_io_service_.reset();
+
         isc_throw(Unexpected, "MtTcpListenerMgr::start failed:" << ex.what());
     }
 }
@@ -125,8 +143,8 @@ MtTcpListenerMgr::stop() {
     // Stop the thread pool.
     thread_pool_->stop();
 
-    // Get rid of the listener.
-    tcp_listener_.reset();
+    // Stop the listener.
+    tcp_listener_->stop();
 
     thread_io_service_->restart();
     try {
@@ -134,6 +152,12 @@ MtTcpListenerMgr::stop() {
     } catch (...) {
     }
 
+    // Get rid of the thread pool.
+    thread_pool_.reset();
+
+    // Get rid of the listener.
+    tcp_listener_.reset();
+
     // Ditch the IOService.
     thread_io_service_.reset();
 
index cd4dc1234576d5b5305830cf113f56521bc50ea0..0e7a1788c8d26ea46ffac9446e209fe32240f097 100644 (file)
@@ -811,8 +811,6 @@ TEST_F(MtTcpListenerMgrTest, basics) {
     ASSERT_THROW_MSG(mt_listener_mgr_->start(), InvalidOperation,
                      "MtTcpListenerMgr already started!");
 
-    return;
-
     // Stop it and verify we're no longer listening.
     ASSERT_NO_THROW_LOG(mt_listener_mgr_->stop());
     ASSERT_TRUE(mt_listener_mgr_->isStopped());
index f75c6cdf4c60cae4d605d4cc670a5294b0bb72cf..9406de89d8b1494ae51975183eab089aefd75986 100644 (file)
@@ -23,7 +23,6 @@ Stopwatch::Stopwatch(const bool autostart)
 }
 
 Stopwatch::~Stopwatch() {
-    delete impl_;
 }
 
 void
index c3d0b2307921eba4908e1040c0e9490da65f45fd..f5c737abbb692d194e6b63fa41acd4dc336623c4 100644 (file)
@@ -118,7 +118,7 @@ public:
 private:
 
     /// @brief Pointer to the @c StopwatchImpl.
-    StopwatchImpl* impl_;
+    boost::shared_ptr<StopwatchImpl> impl_;
 
 };