123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #include <util/generic/yexception.h>
- #include <cerrno>
- #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);
- }
|