daemon.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* Copyright (c) 2003, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "orconfig.h"
  6. #include "lib/process/daemon.h"
  7. #ifndef _WIN32
  8. #include "lib/fs/files.h"
  9. #include "lib/log/torlog.h"
  10. #include "lib/thread/threads.h"
  11. #ifdef HAVE_SYS_TYPES_H
  12. #include <sys/types.h>
  13. #endif
  14. #ifdef HAVE_UNISTD_H
  15. #include <unistd.h>
  16. #endif
  17. #ifdef HAVE_FCNTL_H
  18. #include <fcntl.h>
  19. #endif
  20. #include <errno.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. /* Based on code contributed by christian grothoff */
  24. /** True iff we've called start_daemon(). */
  25. static int start_daemon_called = 0;
  26. /** True iff we've called finish_daemon(). */
  27. static int finish_daemon_called = 0;
  28. /** Socketpair used to communicate between parent and child process while
  29. * daemonizing. */
  30. static int daemon_filedes[2];
  31. /** Start putting the process into daemon mode: fork and drop all resources
  32. * except standard fds. The parent process never returns, but stays around
  33. * until finish_daemon is called. (Note: it's safe to call this more
  34. * than once: calls after the first are ignored.)
  35. */
  36. void
  37. start_daemon(void)
  38. {
  39. pid_t pid;
  40. if (start_daemon_called)
  41. return;
  42. start_daemon_called = 1;
  43. if (pipe(daemon_filedes)) {
  44. /* LCOV_EXCL_START */
  45. log_err(LD_GENERAL,"pipe failed; exiting. Error was %s", strerror(errno));
  46. exit(1); // exit ok: during daemonize, pipe failed.
  47. /* LCOV_EXCL_STOP */
  48. }
  49. pid = fork();
  50. if (pid < 0) {
  51. /* LCOV_EXCL_START */
  52. log_err(LD_GENERAL,"fork failed. Exiting.");
  53. exit(1); // exit ok: during daemonize, fork failed
  54. /* LCOV_EXCL_STOP */
  55. }
  56. if (pid) { /* Parent */
  57. int ok;
  58. char c;
  59. close(daemon_filedes[1]); /* we only read */
  60. ok = -1;
  61. while (0 < read(daemon_filedes[0], &c, sizeof(char))) {
  62. if (c == '.')
  63. ok = 1;
  64. }
  65. fflush(stdout);
  66. if (ok == 1)
  67. exit(0); // exit ok: during daemonize, daemonizing.
  68. else
  69. exit(1); /* child reported error. exit ok: daemonize failed. */
  70. } else { /* Child */
  71. close(daemon_filedes[0]); /* we only write */
  72. (void) setsid(); /* Detach from controlling terminal */
  73. /*
  74. * Fork one more time, so the parent (the session group leader) can exit.
  75. * This means that we, as a non-session group leader, can never regain a
  76. * controlling terminal. This part is recommended by Stevens's
  77. * _Advanced Programming in the Unix Environment_.
  78. */
  79. if (fork() != 0) {
  80. exit(0); // exit ok: during daemonize, fork failed (2)
  81. }
  82. set_main_thread(); /* We are now the main thread. */
  83. return;
  84. }
  85. }
  86. /** Finish putting the process into daemon mode: drop standard fds, and tell
  87. * the parent process to exit. (Note: it's safe to call this more than once:
  88. * calls after the first are ignored. Calls start_daemon first if it hasn't
  89. * been called already.)
  90. */
  91. void
  92. finish_daemon(const char *desired_cwd)
  93. {
  94. int nullfd;
  95. char c = '.';
  96. if (finish_daemon_called)
  97. return;
  98. if (!start_daemon_called)
  99. start_daemon();
  100. finish_daemon_called = 1;
  101. if (!desired_cwd)
  102. desired_cwd = "/";
  103. /* Don't hold the wrong FS mounted */
  104. if (chdir(desired_cwd) < 0) {
  105. log_err(LD_GENERAL,"chdir to \"%s\" failed. Exiting.",desired_cwd);
  106. exit(1); // exit ok: during daemonize, chdir failed.
  107. }
  108. nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
  109. if (nullfd < 0) {
  110. /* LCOV_EXCL_START */
  111. log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
  112. exit(1); // exit ok: during daemonize, couldn't open /dev/null
  113. /* LCOV_EXCL_STOP */
  114. }
  115. /* close fds linking to invoking terminal, but
  116. * close usual incoming fds, but redirect them somewhere
  117. * useful so the fds don't get reallocated elsewhere.
  118. */
  119. if (dup2(nullfd,0) < 0 ||
  120. dup2(nullfd,1) < 0 ||
  121. dup2(nullfd,2) < 0) {
  122. /* LCOV_EXCL_START */
  123. log_err(LD_GENERAL,"dup2 failed. Exiting.");
  124. exit(1); // exit ok: during daemonize, dup2 failed.
  125. /* LCOV_EXCL_STOP */
  126. }
  127. if (nullfd > 2)
  128. close(nullfd);
  129. /* signal success */
  130. if (write(daemon_filedes[1], &c, sizeof(char)) != sizeof(char)) {
  131. log_err(LD_GENERAL,"write failed. Exiting.");
  132. }
  133. close(daemon_filedes[1]);
  134. }
  135. #else /* !(!defined(_WIN32)) */
  136. /* defined(_WIN32) */
  137. void
  138. start_daemon(void)
  139. {
  140. }
  141. void
  142. finish_daemon(const char *cp)
  143. {
  144. (void)cp;
  145. }
  146. #endif /* !defined(_WIN32) */