From: Philipp Gesang Date: Fri, 7 Jan 2022 10:07:19 +0000 (+0100) Subject: add handling of stdio descriptors X-Git-Url: http://developer.intra2net.com/git/?p=libi2ncommon;a=commitdiff_plain;h=f0dfba985e488a3d943b49911e2b3ecfd61e714e add handling of stdio descriptors This completes the daemonization API by adding a function that reassigns the stdio descriptors to /dev/null to prevent the process from being tied IO wise to the terminal it was started on. A ``daemonize_full()`` helper combines all the daemonization steps into a single call. --- diff --git a/src/daemonfunc.cpp b/src/daemonfunc.cpp index 6481493..167f45f 100644 --- a/src/daemonfunc.cpp +++ b/src/daemonfunc.cpp @@ -27,6 +27,7 @@ on this file might be covered by the GNU General Public License. #include #include #include +#include #include #include @@ -254,5 +255,68 @@ pid_t create_session (void) return sid; } +/** + * @brief reopen standard file descriptors as ``/dev/null``. + * + * Disable stdin, stdout and stderr to ensure no output can be read from or + * written to those descriptors. This assumes the process will interact with + * the outside world through other means like syslog and sockets. + * + * Raises ``runtime_error`` in case of errors. + */ +void null_fds () { + int devnull; + + errno = 0; + if ((devnull = open ("/dev/null", O_RDWR)) == -1) + { + throw std::runtime_error + ((std::string) + "null_fds: open(/dev/null) returned an error (" + + I2n::to_string (errno) + + "): " + strerror (errno)); + } + + for (int fd = 0; fd != 3; ++fd) + { + errno = 0; + if (dup2 (devnull, fd) == -1) + { + throw std::runtime_error + ((std::string) + "null_fds: dup2(/dev/null, " + + I2n::to_string (fd) + + ") returned an error (" + + I2n::to_string (errno) + + "): " + strerror (errno)); + } + } + + errno = 0; + if (close (devnull) == -1) + { + throw std::runtime_error + ((std::string) + "null_fds: close(/dev/null) returned an error (" + + I2n::to_string (errno) + + "): " + strerror (errno)); + } +} + +/** + * @brief convert the current process into a background process. + * + * This convenience wrapper combines forking, creation of a new session and + * disabling stdio. + * + * Raises ``runtime_error`` in case of errors. + */ +void daemonize_full (void) +{ + daemonize (); + (void)create_session (); + null_fds (); +} + } } diff --git a/src/daemonfunc.hpp b/src/daemonfunc.hpp index f5b85cf..bcfcc05 100644 --- a/src/daemonfunc.hpp +++ b/src/daemonfunc.hpp @@ -33,6 +33,7 @@ namespace I2n namespace Daemon { void daemonize(); +void daemonize_full(); bool drop_root_privileges(const std::string &username, const std::string &group, bool get_group_from_user=false); @@ -40,6 +41,7 @@ bool drop_root_privileges(const std::string &username, bool pid_of(const std::string& name, std::vector< pid_t >& result); pid_t create_session (void); +void null_fds (void); } }