SNode.C
Loading...
Searching...
No Matches
utils::Daemon Class Reference

#include <Daemon.h>

Collaboration diagram for utils::Daemon:

Public Member Functions

 Daemon ()=delete
 
 ~Daemon ()=delete
 

Static Public Member Functions

static void startDaemon (const std::string &pidFileName, const std::string &userName, const std::string &groupName)
 
static pid_t stopDaemon (const std::string &pidFileName)
 
static void erasePidFile (const std::string &pidFileName)
 

Detailed Description

Definition at line 59 of file Daemon.h.

Constructor & Destructor Documentation

◆ Daemon()

utils::Daemon::Daemon ( )
delete

◆ ~Daemon()

utils::Daemon::~Daemon ( )
delete

Member Function Documentation

◆ erasePidFile()

void utils::Daemon::erasePidFile ( const std::string & pidFileName)
static

Definition at line 178 of file Daemon.cpp.

178 {
179 (void) seteuid(getuid()); // In case we are here seteguid can not fail
180 (void) setegid(getgid()); // In case we are here setegid can not fail
181 std::filesystem::remove(pidFileName); // In case we are here std::Filesystem::remove can not fail
182 }

◆ startDaemon()

void utils::Daemon::startDaemon ( const std::string & pidFileName,
const std::string & userName,
const std::string & groupName )
static

Definition at line 53 of file Daemon.cpp.

53 {
54 if (std::filesystem::exists(pidFileName)) {
55 throw DaemonFailure("Pid file '" + pidFileName + "' exists. Daemon already running?");
56 }
57 errno = 0;
58
59 /* Fork off the parent process */
60 pid_t pid = fork();
61 if (pid < 0) {
62 /* An error occurred */
63 throw DaemonError("First fork()");
64 }
65 if (pid > 0) {
66 /* Success: Let the parent terminate */
67 throw DaemonSignaled("Lead new session", pid);
68 }
69
70 if (setsid() < 0) {
71 /* On success: The child process becomes session leader */
72 throw DaemonError("setsid()");
73 }
74
75 if (signal(SIGHUP, SIG_IGN) == SIG_ERR) {
76 /* Ignore signal sent from parent to child process */
77 throw DaemonError("signal()");
78 }
79
80 /* Fork off for the second time*/
81 pid = fork();
82 if (pid < 0) {
83 /* An error occurred */
84 throw DaemonError("Second fork()");
85 }
86 if (pid > 0) {
87 /* Success: Let the second parent terminate */
88 std::ofstream pidFile(pidFileName, std::ofstream::out);
89
90 if (!pidFile.good()) {
91 kill(pid, SIGTERM);
92 throw DaemonError("Writing pid file '" + pidFileName);
93 }
94 pidFile << pid << std::endl;
95 pidFile.close();
96
97 throw DaemonSignaled("Drop session lead", pid);
98 }
99
100 struct passwd* pw = nullptr;
101 struct group* gr = nullptr;
102
103 if (((void) (errno = 0), gr = getgrnam(groupName.c_str())) == nullptr) {
104 if (errno != 0) {
105 throw DaemonError("getgrnam()");
106 }
107 throw DaemonFailure("getgrname() group not existing");
108 }
109 if (setegid(gr->gr_gid) != 0) {
110 throw DaemonError("setegid()");
111 }
112 if (((void) (errno = 0), (pw = getpwnam(userName.c_str())) == nullptr)) {
113 if (errno != 0) {
114 throw DaemonError("getpwnam()");
115 }
116 throw DaemonFailure("getpwnam() user not existing");
117 }
118 if (seteuid(pw->pw_uid) != 0) {
119 throw DaemonError("seteuid()");
120 } /* Set new file permissions */
121 umask(0);
122 chdir("/");
123
124 close(STDIN_FILENO);
125 close(STDOUT_FILENO);
126 close(STDERR_FILENO);
127
128 if (std::freopen("/dev/null", "r", stdin) == nullptr) {
129 }
130 if (std::freopen("/dev/null", "w+", stdout) == nullptr) {
131 }
132 if (std::freopen("/dev/null", "w+", stderr) == nullptr) {
133 }
134 }
int close(int fd)
Definition unistd.cpp:45
sighandler_t signal(int sig, sighandler_t handler)
Definition signal.cpp:32

◆ stopDaemon()

pid_t utils::Daemon::stopDaemon ( const std::string & pidFileName)
static

Definition at line 136 of file Daemon.cpp.

136 {
137 if (pidFileName.empty()) {
138 throw DaemonFailure("No pid file given");
139 } /* Try to read PID of daemon to from lockfile and kill the daemon */
140 std::ifstream pidFile(pidFileName, std::ifstream::in);
141
142 if (!pidFile.good()) {
143 pidFile.close();
144 throw DaemonError("Reading pid file '" + pidFileName + "'");
145 }
146 pid_t pid = 0;
147 pidFile >> pid;
148 pidFile.close();
149
150 const int pidfd = static_cast<int>(syscall(SYS_pidfd_open, pid, 0)); // NOLINT
151
152 if (pidfd == -1) {
153 erasePidFile(pidFileName);
154 throw DaemonFailure("Daemon not running");
155 }
156 if (kill(pid, SIGTERM) != 0) {
157 throw DaemonError("kill()");
158 }
159 struct pollfd pollfd{};
160 pollfd.fd = pidfd;
161 pollfd.events = POLLIN;
162
163 const int ready = core::system::poll(&pollfd, 1, 5000);
164 close(pidfd);
165
166 if (ready == -1) {
167 throw DaemonError("poll()");
168 }
169 if (ready == 0) {
170 kill(pid, SIGKILL);
171 erasePidFile(pidFileName);
172 throw DaemonFailure("Daemon not responding - killed");
173 }
174
175 return pid;
176 }
static void erasePidFile(const std::string &pidFileName)
Definition Daemon.cpp:178
int poll(pollfd *fds, nfds_t nfds, int timeout)
Definition poll.cpp:32

The documentation for this class was generated from the following files: