From aa482a5e599af2f33ce893dbef2c73a2e6804e3b Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Tue, 28 Jul 2015 15:55:25 +0200 Subject: [PATCH] Add daemonize function to work in the background. [Feature] Add daemonize function to work in the background. [Cause] N/A [Solution] N/A [Verification] Build, run tests, run server as daemon. Change-Id: Ie8987ac4d23ac350ab6036c476ade47436afbe69 --- common/utils/daemon.cpp | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ common/utils/daemon.hpp | 34 ++++++++++++++++++ server/main.cpp | 11 +++++- zone-daemon/main.cpp | 11 +++++- 4 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 common/utils/daemon.cpp create mode 100644 common/utils/daemon.hpp diff --git a/common/utils/daemon.cpp b/common/utils/daemon.cpp new file mode 100644 index 0000000..8ee84c5 --- /dev/null +++ b/common/utils/daemon.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Dariusz Michaluk + * @brief Run a process as a daemon + */ + +#include "fd-utils.hpp" + +#include +#include +#include +#include +#include + +namespace utils { + +bool daemonize() +{ + pid_t pid = ::fork(); + + if (pid == -1) { + std::cerr << "Fork failed" << std::endl; + return false; + } else if (pid != 0) { + exit (0); + } + + if (::setsid() == -1) { + return false; + } + + pid = ::fork(); + + /* + * Fork a second child and exit immediately to prevent zombies. + * This causes the second child process to be orphaned, making the init + * process responsible for its cleanup. And, since the first child is + * a session leader without a controlling terminal, it's possible for + * it to acquire one by opening a terminal in the future (System V + * based systems). This second fork guarantees that the child is no + * longer a session leader, preventing the daemon from ever acquiring + * a controlling terminal. + */ + + if (pid == -1) { + std::cerr << "Fork failed" << std::endl; + return false; + } else if (pid != 0) { + exit(0); + } + + if (::chdir("/") == -1) { + return false; + } + + ::umask(0); + + /** Close all open standard file descriptors */ + int fd = ::open("/dev/null", O_RDWR); + if (fd == -1) { + return false; + } + + for (int i = 0; i <= 2; i++) { + if (::dup2(fd, i) == -1) { + utils::close(fd); + return false; + } + } + utils::close(fd); + + return true; +} + +} // namespace utils diff --git a/common/utils/daemon.hpp b/common/utils/daemon.hpp new file mode 100644 index 0000000..4b5924a --- /dev/null +++ b/common/utils/daemon.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Dariusz Michaluk + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Dariusz Michaluk + * @brief Run a process as a daemon + */ + +#ifndef COMMON_UTILS_DAEMON_HPP +#define COMMON_UTILS_DAEMON_HPP + +namespace utils { + +bool daemonize(); + +} // namespace utils + +#endif // COMMON_UTILS_DAEMON_HPP diff --git a/server/main.cpp b/server/main.cpp index e9440cb..7ed4ef1 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -34,6 +34,7 @@ #include "logger/backend-syslog.hpp" #include "utils/typeinfo.hpp" #include "utils/signal.hpp" +#include "utils/daemon.hpp" #include #include @@ -64,9 +65,10 @@ int main(int argc, char* argv[]) desc.add_options() ("help,h", "print this help") ("root,r", "Don't drop root privileges at startup") - ("version,v", "show application version") + ("daemon,d", "Run server as daemon") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") ("check,c", "check runtime environment and exit") + ("version,v", "show application version") ; po::variables_map vm; @@ -103,6 +105,13 @@ int main(int argc, char* argv[]) return Server::checkEnvironment() ? 0 : 1; } + bool runAsDaemon = vm.count("daemon") > 0; + + if (runAsDaemon && !utils::daemonize()) { + std::cerr << "Failed to daemonize" << std::endl; + return 1; + } + Logger::setLogLevel(vm["log-level"].as()); #if !defined(NDEBUG) Logger::setLogBackend(new StderrBackend()); diff --git a/zone-daemon/main.cpp b/zone-daemon/main.cpp index 58fad9b..1bb3091 100644 --- a/zone-daemon/main.cpp +++ b/zone-daemon/main.cpp @@ -33,6 +33,7 @@ #include "logger/backend-journal.hpp" #include "logger/backend-syslog.hpp" #include "utils/typeinfo.hpp" +#include "utils/daemon.hpp" #include #include @@ -58,8 +59,9 @@ int main(int argc, char* argv[]) desc.add_options() ("help,h", "print this help") - ("version,v", "show application version") + ("daemon,d", "Run server as daemon") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") + ("version,v", "show application version") ; po::variables_map vm; @@ -93,6 +95,13 @@ int main(int argc, char* argv[]) return 0; } + bool runAsDaemon = vm.count("daemon") > 0; + + if (runAsDaemon && !utils::daemonize()) { + std::cerr << "Failed to daemonize" << std::endl; + return 1; + } + Logger::setLogLevel(vm["log-level"].as()); #if !defined(NDEBUG) Logger::setLogBackend(new StderrBackend()); -- 2.7.4