diff options
Diffstat (limited to 'src/daemonizer/posix_fork.cpp')
-rw-r--r-- | src/daemonizer/posix_fork.cpp | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/src/daemonizer/posix_fork.cpp b/src/daemonizer/posix_fork.cpp index d9b4a6d0e..4dff04f3f 100644 --- a/src/daemonizer/posix_fork.cpp +++ b/src/daemonizer/posix_fork.cpp @@ -21,15 +21,43 @@ namespace posix { namespace { - void quit(std::string const & message) + void quit(const std::string & message) { LOG_ERROR(message); throw std::runtime_error(message); } } -void fork() +void fork(const std::string & pidfile) { + // If a PID file is specified, we open the file here, because + // we can't report errors after the fork operation. + // When we fork, we close thise file in each of the parent + // processes. + // Only in the final child process do we write the PID to the + // file (and close it). + std::ofstream pidofs; + if (! pidfile.empty ()) + { + int oldpid; + std::ifstream pidrifs; + pidrifs.open(pidfile, std::fstream::in); + if (! pidrifs.fail()) + { + // Read the PID and send signal 0 to see if the process exists. + if (pidrifs >> oldpid && oldpid > 1 && kill(oldpid, 0) == 0) + { + quit("PID file " + pidfile + " already exists and the PID therein is valid"); + } + pidrifs.close(); + } + + pidofs.open(pidfile, std::fstream::out | std::fstream::trunc); + if (pidofs.fail()) + { + quit("Failed to open specified PID file for writing"); + } + } // 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(). @@ -38,7 +66,7 @@ void fork() if (pid > 0) { // We're in the parent process and need to exit. - // + pidofs.close(); // When the exit() function is used, the program terminates without // invoking local variables' destructors. Only global variables are // destroyed. @@ -59,6 +87,7 @@ void fork() { if (pid > 0) { + pidofs.close(); exit(0); } else @@ -67,6 +96,13 @@ void fork() } } + if (! pidofs.fail()) + { + int pid = ::getpid(); + pidofs << pid << std::endl; + pidofs.close(); + } + // Close the standard streams. This decouples the daemon from the terminal // that started it. close(0); |