aboutsummaryrefslogtreecommitdiffstats
path: root/util/system/daemon.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /util/system/daemon.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'util/system/daemon.cpp')
-rw-r--r--util/system/daemon.cpp168
1 files changed, 168 insertions, 0 deletions
diff --git a/util/system/daemon.cpp b/util/system/daemon.cpp
new file mode 100644
index 0000000000..130e6c8f45
--- /dev/null
+++ b/util/system/daemon.cpp
@@ -0,0 +1,168 @@
+#include <util/generic/yexception.h>
+
+#include <cerrno>
+#include <cstdlib>
+#include <util/system/info.h>
+
+#if defined(_win_)
+ #include <io.h>
+#else
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+#endif
+
+#include "daemon.h"
+
+#ifdef _unix_
+using namespace NDaemonMaker;
+
+static bool Fork(EParent parent) {
+ pid_t pid = fork();
+
+ if (pid > 0) {
+ int status = 0;
+ while (waitpid(pid, &status, 0) < 0 && errno == EINTR) {
+ }
+ if (parent == callExitFromParent) {
+ _exit(0);
+ } else {
+ return true;
+ }
+ } else if (pid < 0) {
+ ythrow TSystemError() << "Cannot fork";
+ }
+
+ if (setsid() < 0) {
+ ythrow TSystemError() << "Cannot setsid";
+ }
+
+ pid = fork();
+
+ if (pid > 0) {
+ _exit(0);
+ } else if (pid < 0) {
+ ythrow TSystemError() << "Cannot second fork";
+ }
+ return false;
+}
+
+#endif
+
+static void CloseFromToExcept(int from, int to, const int* except) {
+ (void)from;
+ (void)to;
+ (void)except;
+
+#ifdef _unix_
+ int mfd = NSystemInfo::MaxOpenFiles();
+ for (int s = from; s < mfd && (to == -1 || s < to); s++) {
+ for (const int* ex = except; *ex >= 0; ++ex) {
+ if (s == *ex) {
+ goto dontclose;
+ }
+ }
+ while (close(s) == -1) {
+ if (errno == EBADF) {
+ break;
+ }
+ if (errno != EINTR) {
+ ythrow TSystemError() << "close(" << s << ") failed";
+ }
+ }
+ dontclose:;
+ }
+#endif /* _unix_ */
+}
+
+bool NDaemonMaker::MakeMeDaemon(ECloseDescriptors cd, EStdIoDescriptors iod, EChDir chd, EParent parent) {
+ (void)cd;
+ (void)iod;
+ (void)chd;
+
+#ifdef _unix_
+ if (Fork(parent)) {
+ return true;
+ }
+
+ if (chd == chdirRoot) {
+ if (chdir("/")) {
+ ythrow TSystemError() << "chdir(\"/\") failed";
+ }
+ }
+
+ int fd[4] = {-1, -1, -1, -1};
+ switch (iod) {
+ case openYandexStd:
+ fd[0] = open("yandex.stdin", O_RDONLY);
+ if (fd[0] < 0) {
+ ythrow TSystemError() << "Cannot open 'yandex.stdin'";
+ }
+ fd[1] = open("yandex.stdout", O_WRONLY | O_APPEND | O_CREAT, 660);
+ if (fd[1] < 0) {
+ ythrow TSystemError() << "Cannot open 'yandex.stdout'";
+ }
+ fd[2] = open("yandex.stderr", O_WRONLY | O_APPEND | O_CREAT, 660);
+ if (fd[2] < 0) {
+ ythrow TSystemError() << "Cannot open 'yandex.stderr'";
+ }
+ break;
+ case openDevNull:
+ fd[0] = open("/dev/null", O_RDWR, 0);
+ break;
+ case openNone:
+ break;
+ default:
+ ythrow yexception() << "Unknown open descriptors mode: " << (int)iod;
+ }
+
+ const int except[4] = {
+ fd[0],
+ fd[1],
+ fd[2],
+ -1};
+ if (closeAll == cd) {
+ CloseFromToExcept(0, -1, except);
+ } else if (closeStdIoOnly == cd) {
+ CloseFromToExcept(0, 3, except);
+ } else {
+ ythrow yexception() << "Unknown close descriptors mode: " << (int)cd;
+ }
+
+ switch (iod) {
+ case openYandexStd:
+ /* Assuming that open(2) acquires fds in order. */
+ dup2(fd[0], STDIN_FILENO);
+ if (fd[0] > 2) {
+ close(fd[0]);
+ }
+ dup2(fd[1], STDOUT_FILENO);
+ if (fd[1] > 2) {
+ close(fd[1]);
+ }
+ dup2(fd[2], STDERR_FILENO);
+ if (fd[2] > 2) {
+ close(fd[2]);
+ }
+ break;
+ case openDevNull:
+ dup2(fd[0], STDIN_FILENO);
+ dup2(fd[0], STDOUT_FILENO);
+ dup2(fd[0], STDERR_FILENO);
+ if (fd[0] > 2) {
+ close(fd[0]);
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+#else
+ return true;
+#endif
+}
+
+void NDaemonMaker::CloseFrom(int fd) {
+ static const int except[1] = {-1};
+ CloseFromToExcept(fd, -1, except);
+}