summaryrefslogtreecommitdiffstats
path: root/src/bin
diff options
context:
space:
mode:
authorThomas Markwalder <tmark@isc.org>2020-02-28 22:04:28 +0100
committerThomas Markwalder <tmark@isc.org>2020-03-04 12:59:52 +0100
commit17580ffc984d264181e177b9d86edfa518f09066 (patch)
tree4314315f9c4fdfa6757b48cfcee17c99025b33a3 /src/bin
parent[#1088] updated ChangeLog (diff)
downloadkea-17580ffc984d264181e177b9d86edfa518f09066.tar.xz
kea-17580ffc984d264181e177b9d86edfa518f09066.zip
[#1115] shutdown command exit-value arg, exit w/failure on db loss
Added exit-value argument to shutdown command. kea-dhcpX servers now exit with EXIT_FAILURE status on db loss src/lib/process/daemon.* Daemon::exit_value_, new member with getter/setter src/lib/process/d_controller.* DControllerBase::launch() - now returns getExitValue() DControllerBase::shutdownHandler() - uses exit-value argument to set exit value src/lib/process/tests/daemon_unittest.cc TEST_F(DaemonTest, exitValue) - new test src/bin/agent/main.cc Use launch() return value for exit value. src/bin/agent/tests/ca_controller_unittests.cc TEST_F(CtrlAgentControllerTest, shutdownExitValue) - new test src/bin/d2/main.cc Use launch() return value for exit value. src/bin/d2/tests/d2_command_unittest.cc TEST_F(CtrlChannelD2Test, shutdownExitValue) - new test src/bin/dhcp4/ctrl_dhcp4_srv.* ControlledDhcpv4Srv:: commandShutdownHandler() - handle exit-value argument shutdown(int exit_value) - added exit_value parameter dbReconnect() - call shutdown(EXIT_FAILURE) dbLostCallback() - call shutdown(EXIT_FAILURE) src/bin/dhcp4/dhcp4_srv.* Dhcp4Srv::run() - returns int Daemon::exit_value instead of bool src/bin/dhcp4/main.cc Use run() return value for exit value. src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc TEST_F(CtrlChannelDhcpv4SrvTest, commands) - revamped test src/bin/dhcp6/ctrl_dhcp6_srv.* ControlledDhcpv6Srv:: commandShutdownHandler() - use exit-value argument to set exit value shutdown(int exit_value) - added exit_value parameter dbReconnect() - call shutdown(EXIT_FAILURE) dbLostCallback() - call shutdown(EXIT_FAILURE) src/bin/dhcp6/dhcp6_srv.* Dhcp6Srv::run() - returns int Daemon::exit_value instead of bool src/bin/dhcp6/main.cc Use run() return value for exit value. src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc TEST_F(CtrlDhcpv6SrvTest, commands) - revamped test
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/agent/main.cc2
-rw-r--r--src/bin/agent/tests/ca_controller_unittests.cc52
-rw-r--r--src/bin/d2/main.cc2
-rw-r--r--src/bin/d2/tests/d2_command_unittest.cc21
-rw-r--r--src/bin/dhcp4/ctrl_dhcp4_srv.cc49
-rw-r--r--src/bin/dhcp4/ctrl_dhcp4_srv.h3
-rw-r--r--src/bin/dhcp4/dhcp4_srv.cc4
-rw-r--r--src/bin/dhcp4/dhcp4_srv.h5
-rw-r--r--src/bin/dhcp4/main.cc2
-rw-r--r--src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc12
-rw-r--r--src/bin/dhcp6/ctrl_dhcp6_srv.cc46
-rw-r--r--src/bin/dhcp6/ctrl_dhcp6_srv.h3
-rw-r--r--src/bin/dhcp6/dhcp6_srv.cc4
-rw-r--r--src/bin/dhcp6/dhcp6_srv.h4
-rw-r--r--src/bin/dhcp6/main.cc2
-rw-r--r--src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc12
16 files changed, 167 insertions, 56 deletions
diff --git a/src/bin/agent/main.cc b/src/bin/agent/main.cc
index be43065b29..42117e5c3a 100644
--- a/src/bin/agent/main.cc
+++ b/src/bin/agent/main.cc
@@ -23,7 +23,7 @@ int main(int argc, char* argv[]) {
DControllerBasePtr& controller = CtrlAgentController::instance();
// 'false' value disables test mode.
- controller->launch(argc, argv, false);
+ ret = controller->launch(argc, argv, false);
} catch (const VersionMessage& ex) {
std::string msg(ex.what());
if (!msg.empty()) {
diff --git a/src/bin/agent/tests/ca_controller_unittests.cc b/src/bin/agent/tests/ca_controller_unittests.cc
index dcda359c97..0c084daf9a 100644
--- a/src/bin/agent/tests/ca_controller_unittests.cc
+++ b/src/bin/agent/tests/ca_controller_unittests.cc
@@ -697,4 +697,56 @@ TEST_F(CtrlAgentControllerTest, statusGet) {
EXPECT_GE(found_reload->intValue(), 0);
}
+TEST_F(CtrlAgentControllerTest, shutdownExitValue) {
+ ASSERT_NO_THROW(initProcess());
+ EXPECT_TRUE(checkProcess());
+
+ // The framework available makes it very difficult to test the actual
+ // code as CtrlAgentController is not initialized the same way it is
+ // in production code. In particular, the way CtrlAgentController
+ // is initialized in tests does not call registerCommands().
+ // This is a crude workaround for this problem. Proper solution should
+ // be developed sooner rather than later.
+ const DControllerBasePtr& base = getController();
+ const CtrlAgentControllerPtr& ctrl
+ = boost::dynamic_pointer_cast<CtrlAgentController>(base);
+ ASSERT_TRUE(ctrl);
+ // Now clean up after ourselves.
+ ctrl->registerCommands();
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ getController()->setConfigFile("testvalid.json");
+
+ // Ok, enough fooling around. Let's create a valid config.
+ ofstream f("testvalid.json", ios::trunc);
+ f << "{ \"Control-agent\": "
+ << string(valid_agent_config)
+ << " }" << endl;
+ f.close();
+
+ // Build and execute the command.
+
+ ConstElementPtr cmd = Element::fromJSON("{ \"command\": \"shutdown\"}");
+ ConstElementPtr params = Element::fromJSON("{ \"exit-value\": 77 }");
+ ConstElementPtr answer;
+ answer = CtrlAgentCommandMgr::instance().handleCommand("shutdown",
+ params, cmd);
+
+ // Verify the reload was successful.
+ string expected = "[ { \"result\": 0, \"text\": "
+ "\"Control Agent is shutting down\" } ]";
+
+ EXPECT_EQ(expected, answer->str());
+
+ int exit_value = ctrl->getExitValue();
+ EXPECT_EQ(77, exit_value);
+
+ // Remove the file.
+ ::remove("testvalid.json");
+
+ // Now clean up after ourselves.
+ ctrl->deregisterCommands();
+}
+
}
diff --git a/src/bin/d2/main.cc b/src/bin/d2/main.cc
index 7eb704467b..1f896fcb83 100644
--- a/src/bin/d2/main.cc
+++ b/src/bin/d2/main.cc
@@ -32,7 +32,7 @@ int main(int argc, char* argv[]) {
DControllerBasePtr& controller = D2Controller::instance();
// 'false' value disables test mode.
- controller->launch(argc, argv, false);
+ ret = controller->launch(argc, argv, false);
} catch (const VersionMessage& ex) {
std::string msg(ex.what());
if (!msg.empty()) {
diff --git a/src/bin/d2/tests/d2_command_unittest.cc b/src/bin/d2/tests/d2_command_unittest.cc
index c6690d75e2..e0eceafacb 100644
--- a/src/bin/d2/tests/d2_command_unittest.cc
+++ b/src/bin/d2/tests/d2_command_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -565,7 +565,7 @@ TEST_F(CtrlChannelD2Test, invalid) {
response);
}
-// Tests that the server properly responds to shtudown command.
+// Tests that the server properly responds to shutdown command.
TEST_F(CtrlChannelD2Test, shutdown) {
EXPECT_NO_THROW(createUnixChannelServer());
string response;
@@ -573,6 +573,23 @@ TEST_F(CtrlChannelD2Test, shutdown) {
sendUnixCommand("{ \"command\": \"shutdown\" }", response);
EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutdown initiated, type is: normal\" }",
response);
+ EXPECT_EQ(EXIT_SUCCESS, server_->getExitValue());
+}
+
+// Tests that the server sets exit value supplied as argument
+// to shutdown command.
+TEST_F(CtrlChannelD2Test, shutdownExitValue) {
+ EXPECT_NO_THROW(createUnixChannelServer());
+ string response;
+
+ sendUnixCommand("{ \"command\": \"shutdown\", "
+ "\"arguments\": { \"exit-value\": 77 }}"
+ , response);
+
+ EXPECT_EQ("{ \"result\": 0, \"text\": \"Shutdown initiated, type is: normal\" }",
+ response);
+
+ EXPECT_EQ(77, server_->getExitValue());
}
// This test verifies that the DHCP server handles version-get commands.
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.cc b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
index 2b298dfbf6..8e00344e7a 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.cc
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.cc
@@ -202,17 +202,32 @@ ControlledDhcpv4Srv::loadConfigFile(const std::string& file_name) {
}
ConstElementPtr
-ControlledDhcpv4Srv::commandShutdownHandler(const string&, ConstElementPtr) {
- if (ControlledDhcpv4Srv::getInstance()) {
- ControlledDhcpv4Srv::getInstance()->shutdown();
- } else {
+ControlledDhcpv4Srv::commandShutdownHandler(const string&, ConstElementPtr args) {
+ if (!ControlledDhcpv4Srv::getInstance()) {
LOG_WARN(dhcp4_logger, DHCP4_NOT_RUNNING);
- ConstElementPtr answer = isc::config::createAnswer(1,
- "Shutdown failure.");
- return (answer);
+ return(createAnswer(CONTROL_RESULT_ERROR, "Shutdown failure."));
}
- ConstElementPtr answer = isc::config::createAnswer(0, "Shutting down.");
- return (answer);
+
+ int exit_value = 0;
+ if (args) {
+ // @todo Should we go ahead and shutdown even if the args are invalid?
+ if (args->getType() != Element::map) {
+ return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
+ }
+
+ ConstElementPtr param = args->get("exit-value");
+ if (param) {
+ if (param->getType() != Element::integer) {
+ return (createAnswer(CONTROL_RESULT_ERROR,
+ "parameter 'exit-value' is not an integer"));
+ }
+
+ exit_value = param->intValue();
+ }
+ }
+
+ ControlledDhcpv4Srv::getInstance()->shutdown(exit_value);
+ return(createAnswer(CONTROL_RESULT_SUCCESS, "Shutting down."));
}
ConstElementPtr
@@ -957,9 +972,10 @@ ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t server_port /*= DHCP4_SERVER_P
boost::bind(&StatsMgr::statisticSetMaxSampleCountAllHandler, _1, _2));
}
-void ControlledDhcpv4Srv::shutdown() {
- io_service_.stop(); // Stop ASIO transmissions
- Dhcpv4Srv::shutdown(); // Initiate DHCPv4 shutdown procedure.
+void ControlledDhcpv4Srv::shutdown(int exit_value) {
+ setExitValue(exit_value);
+ io_service_.stop(); // Stop ASIO transmissions
+ Dhcpv4Srv::shutdown(); // Initiate DHCPv4 shutdown procedure.
}
ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
@@ -1065,9 +1081,10 @@ ControlledDhcpv4Srv::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
db_reconnect_ctl.reset();
} else {
if (!db_reconnect_ctl->checkRetries()) {
+ // We're out of retries, log it and initiate shutdown.
LOG_ERROR(dhcp4_logger, DHCP4_DB_RECONNECT_RETRIES_EXHAUSTED)
.arg(db_reconnect_ctl->maxRetries());
- shutdown();
+ shutdown(EXIT_FAILURE);
return;
}
@@ -1099,14 +1116,14 @@ ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
return (false);
}
- // If reconnect isn't enabled or we're out of retries,
- // log it, schedule a shutdown, and return false
+ // If reconnect isn't enabled log it,
+ // initiate a shutdown and return false.
if (!db_reconnect_ctl->retriesLeft() ||
!db_reconnect_ctl->retryInterval()) {
LOG_INFO(dhcp4_logger, DHCP4_DB_RECONNECT_DISABLED)
.arg(db_reconnect_ctl->retriesLeft())
.arg(db_reconnect_ctl->retryInterval());
- ControlledDhcpv4Srv::processCommand("shutdown", ConstElementPtr());
+ shutdown(EXIT_FAILURE);
return(false);
}
diff --git a/src/bin/dhcp4/ctrl_dhcp4_srv.h b/src/bin/dhcp4/ctrl_dhcp4_srv.h
index b50479681a..d1f8107751 100644
--- a/src/bin/dhcp4/ctrl_dhcp4_srv.h
+++ b/src/bin/dhcp4/ctrl_dhcp4_srv.h
@@ -63,7 +63,8 @@ public:
void cleanup();
/// @brief Initiates shutdown procedure for the whole DHCPv4 server.
- void shutdown();
+ /// @param exit_value integer value to the process should exit with.
+ void shutdown(int exit_value);
/// @brief Command processor
///
diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc
index d5b2c34846..6d20213631 100644
--- a/src/bin/dhcp4/dhcp4_srv.cc
+++ b/src/bin/dhcp4/dhcp4_srv.cc
@@ -771,7 +771,7 @@ Dhcpv4Srv::sendPacket(const Pkt4Ptr& packet) {
IfaceMgr::instance().send(packet);
}
-bool
+int
Dhcpv4Srv::run() {
#ifdef ENABLE_AFL
// Set up structures needed for fuzzing.
@@ -805,7 +805,7 @@ Dhcpv4Srv::run() {
// destroying the thread pool
MultiThreadingMgr::instance().apply(false, 0);
- return (true);
+ return (getExitValue());
}
void
diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h
index 3af4f97eb5..4ade966691 100644
--- a/src/bin/dhcp4/dhcp4_srv.h
+++ b/src/bin/dhcp4/dhcp4_srv.h
@@ -272,8 +272,8 @@ public:
/// Main server processing loop. Call the processing step routine
/// until shut down.
///
- /// @return true, if being shut down gracefully, never fail.
- bool run();
+ /// @return The value returned by @c Daemon::getExitValue().
+ int run();
/// @brief Main server processing step.
///
@@ -319,7 +319,6 @@ public:
void processPacket(Pkt4Ptr& query, Pkt4Ptr& rsp,
bool allow_packet_park = true);
-
/// @brief Instructs the server to shut down.
void shutdown();
diff --git a/src/bin/dhcp4/main.cc b/src/bin/dhcp4/main.cc
index b8cd9a5205..9d72cebaab 100644
--- a/src/bin/dhcp4/main.cc
+++ b/src/bin/dhcp4/main.cc
@@ -269,7 +269,7 @@ main(int argc, char* argv[]) {
LOG_INFO(dhcp4_logger, DHCP4_STARTED).arg(VERSION);
// And run the main loop of the server.
- server.run();
+ ret = server.run();
LOG_INFO(dhcp4_logger, DHCP4_SHUTDOWN);
diff --git a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
index 8930bc2aec..b3533d99c9 100644
--- a/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
+++ b/src/bin/dhcp4/tests/ctrl_dhcp4_srv_unittest.cc
@@ -401,15 +401,19 @@ TEST_F(CtrlChannelDhcpv4SrvTest, commands) {
result = ControlledDhcpv4Srv::processCommand("shutdown", params);
comment = parseAnswer(rcode, result);
EXPECT_EQ(0, rcode); // expect success
+ // Exit value should default to 0.
+ EXPECT_EQ(0, server_->getExitValue());
- const pid_t pid(getpid());
- ConstElementPtr x(new isc::data::IntElement(pid));
- params->set("pid", x);
+ // Case 3: send shutdown command with exit-value parameter.
+ ConstElementPtr x(new isc::data::IntElement(77));
+ params->set("exit-value", x);
- // Case 3: send shutdown command with 1 parameter: pid
result = ControlledDhcpv4Srv::processCommand("shutdown", params);
comment = parseAnswer(rcode, result);
EXPECT_EQ(0, rcode); // expect success
+
+ // Exit value should match.
+ EXPECT_EQ(77, server_->getExitValue());
}
// Check that the "libreload" command will reload libraries
diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.cc b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
index 69cce5d4f0..e8bb15af05 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.cc
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.cc
@@ -205,16 +205,33 @@ void ControlledDhcpv6Srv::cleanup() {
}
ConstElementPtr
-ControlledDhcpv6Srv::commandShutdownHandler(const string&, ConstElementPtr) {
- if (ControlledDhcpv6Srv::getInstance()) {
- ControlledDhcpv6Srv::getInstance()->shutdown();
- } else {
+ControlledDhcpv6Srv::commandShutdownHandler(const string&, ConstElementPtr args) {
+
+ if (!ControlledDhcpv6Srv::getInstance()) {
LOG_WARN(dhcp6_logger, DHCP6_NOT_RUNNING);
- ConstElementPtr answer = isc::config::createAnswer(1, "Shutdown failure.");
- return (answer);
+ return(createAnswer(CONTROL_RESULT_ERROR, "Shutdown failure."));
}
- ConstElementPtr answer = isc::config::createAnswer(0, "Shutting down.");
- return (answer);
+
+ int exit_value = 0;
+ if (args) {
+ // @todo Should we go ahead and shutdown even if the args are invalid?
+ if (args->getType() != Element::map) {
+ return (createAnswer(CONTROL_RESULT_ERROR, "Argument must be a map"));
+ }
+
+ ConstElementPtr param = args->get("exit-value");
+ if (param) {
+ if (param->getType() != Element::integer) {
+ return (createAnswer(CONTROL_RESULT_ERROR,
+ "parameter 'exit-value' is not an integer"));
+ }
+
+ exit_value = param->intValue();
+ }
+ }
+
+ ControlledDhcpv6Srv::getInstance()->shutdown(exit_value);
+ return(createAnswer(CONTROL_RESULT_SUCCESS, "Shutting down."));
}
ConstElementPtr
@@ -977,8 +994,9 @@ ControlledDhcpv6Srv::ControlledDhcpv6Srv(uint16_t server_port,
boost::bind(&StatsMgr::statisticSetMaxSampleCountAllHandler, _1, _2));
}
-void ControlledDhcpv6Srv::shutdown() {
- io_service_.stop(); // Stop ASIO transmissions
+void ControlledDhcpv6Srv::shutdown(int exit_value) {
+ setExitValue(exit_value);
+ io_service_.stop(); // Stop ASIO transmissions
Dhcpv6Srv::shutdown(); // Initiate DHCPv6 shutdown procedure.
}
@@ -1085,9 +1103,10 @@ ControlledDhcpv6Srv::dbReconnect(ReconnectCtlPtr db_reconnect_ctl) {
db_reconnect_ctl.reset();
} else {
if (!db_reconnect_ctl->checkRetries()) {
+ // We're out of retries, log it and initiate shutdown.
LOG_ERROR(dhcp6_logger, DHCP6_DB_RECONNECT_RETRIES_EXHAUSTED)
.arg(db_reconnect_ctl->maxRetries());
- shutdown();
+ shutdown(EXIT_FAILURE);
return;
}
@@ -1119,14 +1138,13 @@ ControlledDhcpv6Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
return (false);
}
- // If reconnect isn't enabled or we're out of retries,
- // log it, schedule a shutdown, and return false
+ // If reconnect isn't enabled log it and initiate a shutdown.
if (!db_reconnect_ctl->retriesLeft() ||
!db_reconnect_ctl->retryInterval()) {
LOG_INFO(dhcp6_logger, DHCP6_DB_RECONNECT_DISABLED)
.arg(db_reconnect_ctl->retriesLeft())
.arg(db_reconnect_ctl->retryInterval());
- ControlledDhcpv6Srv::processCommand("shutdown", ConstElementPtr());
+ shutdown(EXIT_FAILURE);
return(false);
}
diff --git a/src/bin/dhcp6/ctrl_dhcp6_srv.h b/src/bin/dhcp6/ctrl_dhcp6_srv.h
index 6061630b33..911eb01908 100644
--- a/src/bin/dhcp6/ctrl_dhcp6_srv.h
+++ b/src/bin/dhcp6/ctrl_dhcp6_srv.h
@@ -63,7 +63,8 @@ public:
void cleanup();
/// @brief Initiates shutdown procedure for the whole DHCPv6 server.
- void shutdown();
+ /// @param exit_value integer value to the process should exit with.
+ virtual void shutdown(int exit_value);
/// @brief Command processor
///
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 1f28dd4a12..5aa4321e39 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/src/bin/dhcp6/dhcp6_srv.cc
@@ -442,7 +442,7 @@ Dhcpv6Srv::initContext(const Pkt6Ptr& pkt,
evaluateClasses(pkt, true);
}
-bool Dhcpv6Srv::run() {
+int Dhcpv6Srv::run() {
#ifdef ENABLE_AFL
// Set up structures needed for fuzzing.
Fuzz fuzzer(6, server_port_);
@@ -475,7 +475,7 @@ bool Dhcpv6Srv::run() {
// destroying the thread pool
MultiThreadingMgr::instance().apply(false, 0);
- return (true);
+ return (getExitValue());
}
void Dhcpv6Srv::run_one() {
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index 59fa57f13d..b1716340ac 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -139,8 +139,8 @@ public:
/// Main server processing loop. Call the processing step routine
/// until shut down.
///
- /// @return true, if being shut down gracefully, never fail.
- bool run();
+ /// @return The value returned by @c Daemon::getExitValue().
+ int run();
/// @brief Main server processing step.
///
diff --git a/src/bin/dhcp6/main.cc b/src/bin/dhcp6/main.cc
index 893107d84f..b4fde4cbd4 100644
--- a/src/bin/dhcp6/main.cc
+++ b/src/bin/dhcp6/main.cc
@@ -269,7 +269,7 @@ main(int argc, char* argv[]) {
LOG_INFO(dhcp6_logger, DHCP6_STARTED).arg(VERSION);
// And run the main loop of the server.
- server.run();
+ ret = server.run();
LOG_INFO(dhcp6_logger, DHCP6_SHUTDOWN);
diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
index e81065716f..3a9259e4a5 100644
--- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
+++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2019 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -419,14 +419,16 @@ TEST_F(CtrlDhcpv6SrvTest, commands) {
comment = parseAnswer(rcode, result);
EXPECT_EQ(0, rcode); // expect success
- const pid_t pid(getpid());
- ConstElementPtr x(new isc::data::IntElement(pid));
- params->set("pid", x);
+ // Case 3: send shutdown command with exit-value parameter.
+ ConstElementPtr x(new isc::data::IntElement(77));
+ params->set("exit-value", x);
- // Case 3: send shutdown command with 1 parameter: pid
result = ControlledDhcpv6Srv::processCommand("shutdown", params);
comment = parseAnswer(rcode, result);
EXPECT_EQ(0, rcode); // expect success
+
+ // Exit value should match.
+ EXPECT_EQ(77, srv->getExitValue());
}
// Check that the "libreload" command will reload libraries