aboutsummaryrefslogtreecommitdiff
path: root/src/daemonizer/posix_fork.cpp
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2015-03-24 08:50:08 +0200
committerRiccardo Spagni <ric@spagni.net>2015-03-24 08:53:05 +0200
commitd7286395c97afd9d33d6170c1cf24f1e38140b37 (patch)
tree5513e1477d68755a44e0b0c7d34542b1c75eb99d /src/daemonizer/posix_fork.cpp
parentupdated gtest to latest (diff)
parentMerge upstream to daemonize changes (diff)
downloadmonero-d7286395c97afd9d33d6170c1cf24f1e38140b37.tar.xz
Merge pull request #243
51e3579 Fixed bug in static linking boost on MINGW (Thomas Winget) f78bb00 Hopefully fixes build on Windows for real this time (Thomas Winget) 2b0583b Hopefully fixes build on Windows (Thomas Winget) 9dab105 DNS checkpoint loading for testnet should now be correct (Thomas Winget) 52f9629 sending commands to forked daemon works on testnet now (Thomas Winget) 76289d0 Fix tests building -- function signatures changed (Thomas Winget) db53e19 revert stop_daemon method to use correct exit (Thomas Winget) 96cbecf RPC calls for background daemon added in (Thomas Winget) 9193d6f Daemonize changes pulled in -- daemon builds (Thomas Winget)
Diffstat (limited to 'src/daemonizer/posix_fork.cpp')
-rw-r--r--src/daemonizer/posix_fork.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp
new file mode 100644
index 000000000..c068912ec
--- /dev/null
+++ b/src/daemonizer/posix_fork.cpp
@@ -0,0 +1,108 @@
+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include "daemonizer/posix_fork.h"
+#include "misc_log_ex.h"
+
+#include <cstdlib>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdexcept>
+#include <string>
+#include <sys/stat.h>
+
+namespace posix {
+
+namespace {
+ void quit(std::string const & message)
+ {
+ LOG_ERROR(message);
+ throw std::runtime_error(message);
+ }
+}
+
+void fork()
+{
+ // Fork the process and have the parent exit. If the process was started
+ // from a shell, this returns control to the user. Forking a new process is
+ // also a prerequisite for the subsequent call to setsid().
+ if (pid_t pid = ::fork())
+ {
+ if (pid > 0)
+ {
+ // We're in the parent process and need to exit.
+ //
+ // When the exit() function is used, the program terminates without
+ // invoking local variables' destructors. Only global variables are
+ // destroyed.
+ exit(0);
+ }
+ else
+ {
+ quit("First fork failed");
+ }
+ }
+
+ // Make the process a new session leader. This detaches it from the
+ // terminal.
+ setsid();
+
+ // A process inherits its working directory from its parent. This could be
+ // on a mounted filesystem, which means that the running daemon would
+ // prevent this filesystem from being unmounted. Changing to the root
+ // directory avoids this problem.
+ if (chdir("/") < 0)
+ {
+ quit("Unable to change working directory to root");
+ }
+
+ // The file mode creation mask is also inherited from the parent process.
+ // We don't want to restrict the permissions on files created by the
+ // daemon, so the mask is cleared.
+ umask(0);
+
+ // A second fork ensures the process cannot acquire a controlling terminal.
+ if (pid_t pid = ::fork())
+ {
+ if (pid > 0)
+ {
+ exit(0);
+ }
+ else
+ {
+ quit("Second fork failed");
+ }
+ }
+
+ // Close the standard streams. This decouples the daemon from the terminal
+ // that started it.
+ close(0);
+ close(1);
+ close(2);
+
+ // We don't want the daemon to have any standard input.
+ if (open("/dev/null", O_RDONLY) < 0)
+ {
+ quit("Unable to open /dev/null");
+ }
+
+ // Send standard output to a log file.
+ const char* output = "/tmp/bitmonero.daemon.stdout.stderr";
+ const int flags = O_WRONLY | O_CREAT | O_APPEND;
+ const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+ if (open(output, flags, mode) < 0)
+ {
+ quit("Unable to open output file: " + std::string(output));
+ }
+
+ // Also send standard error to the same log file.
+ if (dup(1) < 0)
+ {
+ quit("Unable to dup output descriptor");
+ }
+}
+
+} // namespace posix