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 81 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 200 of file Daemon.cpp.

200 {
201 (void) seteuid(getuid()); // In case we are here seteguid can not fail
202 (void) setegid(getgid()); // In case we are here setegid can not fail
203 std::filesystem::remove(pidFileName); // In case we are here std::Filesystem::remove can not fail
204 }

Referenced by stopDaemon(), and utils::Config::terminate().

Here is the caller graph for this function:

◆ startDaemon()

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

Definition at line 75 of file Daemon.cpp.

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

References utils::DaemonError::DaemonError(), utils::DaemonFailure::DaemonFailure(), and utils::DaemonSignaled::DaemonSignaled().

Referenced by utils::Config::bootstrap().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stopDaemon()

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

Definition at line 158 of file Daemon.cpp.

158 {
159 if (pidFileName.empty()) {
160 throw DaemonFailure("No pid file given");
161 } /* Try to read PID of daemon to from lockfile and kill the daemon */
162 std::ifstream pidFile(pidFileName, std::ifstream::in);
163
164 if (!pidFile.good()) {
165 pidFile.close();
166 throw DaemonError("Reading pid file '" + pidFileName + "'");
167 }
168 pid_t pid = 0;
169 pidFile >> pid;
170 pidFile.close();
171
172 const int pidfd = static_cast<int>(syscall(SYS_pidfd_open, pid, 0)); // NOLINT
173
174 if (pidfd == -1) {
175 erasePidFile(pidFileName);
176 throw DaemonFailure("Daemon not running");
177 }
178 if (kill(pid, SIGTERM) != 0) {
179 throw DaemonError("kill()");
180 }
181 struct pollfd pollfd{};
182 pollfd.fd = pidfd;
183 pollfd.events = POLLIN;
184
185 const int ready = core::system::poll(&pollfd, 1, 5000);
186 close(pidfd);
187
188 if (ready == -1) {
189 throw DaemonError("poll()");
190 }
191 if (ready == 0) {
192 kill(pid, SIGKILL);
193 erasePidFile(pidFileName);
194 throw DaemonFailure("Daemon not responding - killed");
195 }
196
197 return pid;
198 }
static void erasePidFile(const std::string &pidFileName)
Definition Daemon.cpp:200
int poll(pollfd *fds, nfds_t nfds, int timeout)
Definition poll.cpp:54

References utils::DaemonError::DaemonError(), utils::DaemonFailure::DaemonFailure(), and erasePidFile().

Referenced by utils::Config::parse1().

Here is the call graph for this function:
Here is the caller graph for this function:

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