daemon.c 4.4 KB

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