daemon.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <cc/data.h>
  8. #include <dhcpsrv/cfgmgr.h>
  9. #include <dhcpsrv/daemon.h>
  10. #include <exceptions/exceptions.h>
  11. #include <log/logger_name.h>
  12. #include <log/logger_support.h>
  13. #include <logging.h>
  14. #include <util/filename.h>
  15. #include <boost/bind.hpp>
  16. #include <sstream>
  17. #include <errno.h>
  18. /// @brief provides default implementation for basic daemon operations
  19. ///
  20. /// This file provides stub implementations that are expected to be redefined
  21. /// in derived classes (e.g. ControlledDhcpv6Srv)
  22. namespace isc {
  23. namespace dhcp {
  24. Daemon::Daemon()
  25. : signal_set_(), signal_handler_(), config_file_(""), proc_name_(""),
  26. pid_file_dir_(DHCP_DATA_DIR), pid_file_(), am_file_author_(false) {
  27. // The pid_file_dir can be overridden via environment variable
  28. // This is primarily intended to simplify testing
  29. const char* const env = getenv("KEA_PIDFILE_DIR");
  30. if (env) {
  31. pid_file_dir_ = env;
  32. }
  33. }
  34. Daemon::~Daemon() {
  35. if (pid_file_ && am_file_author_) {
  36. pid_file_->deleteFile();
  37. }
  38. }
  39. void Daemon::cleanup() {
  40. }
  41. void Daemon::shutdown() {
  42. }
  43. void Daemon::handleSignal() {
  44. if (signal_set_ && signal_handler_) {
  45. signal_set_->handleNext(boost::bind(signal_handler_, _1));
  46. }
  47. }
  48. void Daemon::configureLogger(const isc::data::ConstElementPtr& log_config,
  49. const SrvConfigPtr& storage) {
  50. if (log_config) {
  51. isc::data::ConstElementPtr loggers = log_config->get("loggers");
  52. if (loggers) {
  53. LogConfigParser parser(storage);
  54. parser.parseConfiguration(loggers, CfgMgr::instance().isVerbose());
  55. }
  56. }
  57. }
  58. void
  59. Daemon::setVerbose(bool verbose) {
  60. CfgMgr::instance().setVerbose(verbose);
  61. }
  62. bool
  63. Daemon::getVerbose() const {
  64. return (CfgMgr::instance().isVerbose());
  65. }
  66. void Daemon::loggerInit(const char* name, bool verbose) {
  67. setenv("KEA_LOGGER_DESTINATION", "stdout", 0);
  68. // Initialize logger system
  69. isc::log::initLogger(name, isc::log::DEBUG, isc::log::MAX_DEBUG_LEVEL,
  70. NULL);
  71. // Apply default configuration (log INFO or DEBUG to stdout)
  72. isc::log::setDefaultLoggingOutput(verbose);
  73. }
  74. std::string Daemon::getVersion(bool /*extended*/) {
  75. isc_throw(isc::NotImplemented, "Daemon::getVersion() called");
  76. }
  77. std::string
  78. Daemon::getConfigFile() const {
  79. return (config_file_);
  80. }
  81. void
  82. Daemon::setConfigFile(const std::string& config_file) {
  83. config_file_ = config_file;
  84. }
  85. std::string
  86. Daemon::getProcName() const {
  87. return (proc_name_);
  88. };
  89. void
  90. Daemon::setProcName(const std::string& proc_name) {
  91. proc_name_ = proc_name;
  92. }
  93. std::string
  94. Daemon::getPIDFileDir() const {
  95. return(pid_file_dir_);
  96. }
  97. void
  98. Daemon::setPIDFileDir(const std::string& pid_file_dir) {
  99. pid_file_dir_ = pid_file_dir;
  100. }
  101. std::string
  102. Daemon::getPIDFileName() const {
  103. if (pid_file_) {
  104. return (pid_file_->getFilename());
  105. }
  106. return ("");
  107. };
  108. void
  109. Daemon::setPIDFileName(const std::string& pid_file_name) {
  110. if (pid_file_) {
  111. isc_throw(isc::InvalidOperation, "Daemon::setConfigFile"
  112. " file name already set to:" << pid_file_->getFilename());
  113. }
  114. if (pid_file_name.empty()) {
  115. isc_throw(isc::BadValue, "Daemon::setPIDFileName"
  116. " file name may not be empty");
  117. }
  118. pid_file_.reset(new util::PIDFile(pid_file_name));
  119. };
  120. std::string
  121. Daemon::makePIDFileName() const {
  122. if (config_file_.empty()) {
  123. isc_throw(isc::InvalidOperation,
  124. "Daemon::makePIDFileName config file name is not set");
  125. }
  126. if (proc_name_.empty()) {
  127. isc_throw(isc::InvalidOperation,
  128. "Daemon::makePIDFileName process name is not set");
  129. }
  130. // Create Filename instance from the config_file_ pathname, so we can
  131. // extract the fname component.
  132. isc::util::Filename file(config_file_);
  133. if (file.name().empty()) {
  134. isc_throw(isc::BadValue, "Daemon::makePIDFileName config file:"
  135. << config_file_ << " is missing file name");
  136. }
  137. // Make the pathname for the PID file from the runtime directory,
  138. // configuration name and process name.
  139. std::ostringstream stream;
  140. stream << pid_file_dir_ << "/" << file.name()
  141. << "." << proc_name_ << ".pid";
  142. return(stream.str());
  143. };
  144. void
  145. Daemon::createPIDFile(int pid) {
  146. // If pid_file_ hasn't been instantiated explicitly, then do so
  147. // using the default name.
  148. if (!pid_file_) {
  149. setPIDFileName(makePIDFileName());
  150. }
  151. // If we find a pre-existing file containing a live PID we bail.
  152. int chk_pid = pid_file_->check();
  153. if (chk_pid > 0) {
  154. isc_throw(DaemonPIDExists, "Daemon::createPIDFile: PID: " << chk_pid
  155. << " exists, PID file: " << getPIDFileName());
  156. }
  157. if (pid == 0) {
  158. // Write the PID of the current process
  159. pid_file_->write();
  160. } else {
  161. // Write the PID we were given
  162. pid_file_->write(pid);
  163. }
  164. am_file_author_ = true;
  165. }
  166. };
  167. };