VirtualBox

Changeset 11337 in vbox for trunk/src/VBox/Runtime/r3/posix


Ignore:
Timestamp:
Aug 11, 2008 3:15:13 PM (16 years ago)
Author:
vboxsync
Message:

Runtime: new function for daemonizing, implemented on posix systems only so far.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/posix/process-posix.cpp

    r8245 r11337  
    3838#include <stdlib.h>
    3939#include <errno.h>
     40#include <sys/types.h>
    4041#include <sys/stat.h>
    4142#include <sys/wait.h>
     43#include <fcntl.h>
    4244#include <signal.h>
    4345#if defined(RT_OS_LINUX) || defined(RT_OS_OS2)
     
    275277}
    276278
     279/**
     280 * Daemonize the current process, making it a background process. The current
     281 * process will exit if daemonizing is successful.
     282 *
     283 * @returns iprt status code.
     284 * @param   fNoChDir    Pass false to change working directory to "/".
     285 * @param   fNoClose    Pass false to redirect standard file streams to the null device.
     286 * @param   pszPidfile  Path to a file to write the process id of the daemon
     287 *                      process to. Daemonizing will fail if this file already
     288 *                      exists or cannot be written. May be NULL.
     289 */
     290RTR3DECL(int)   RTProcDaemonize(bool fNoChDir, bool fNoClose, const char *pszPidfile)
     291{
     292    /*
     293     * Fork the child process in a new session and quit the parent.
     294     *
     295     * - fork once and create a new session (setsid). This will detach us
     296     *   from the controlling tty meaning that we won't receive the SIGHUP
     297     *   (or any other signal) sent to that session.
     298     * - The SIGHUP signal is ignored because the session/parent may throw
     299     *   us one before we get to the setsid.
     300     * - When the parent exit(0) we will become an orphan and re-parented to
     301     *   the init process.
     302     * - Because of the sometimes unexpected semantics of assigning the
     303     *   controlling tty automagically when a session leader first opens a tty,
     304     *   we will fork() once more to get rid of the session leadership role.
     305     */
     306
     307    /* We start off by opening the pidfile, so that we can fail straight away
     308     * if it already exists. */
     309    int fdPidfile = -1;
     310    if (pszPidfile != NULL)
     311    {
     312        /* @note the exclusive create is not guaranteed on all file
     313         * systems (e.g. NFSv2) */
     314        if ((fdPidfile = open(pszPidfile, O_RDWR | O_CREAT | O_EXCL, 0644)) == -1)
     315            return RTErrConvertFromErrno(errno);
     316    }
     317
     318    /* Ignore SIGHUP straight away. */
     319    struct sigaction OldSigAct;
     320    struct sigaction SigAct;
     321    memset(&SigAct, 0, sizeof(SigAct));
     322    SigAct.sa_handler = SIG_IGN;
     323    int rcSigAct = sigaction(SIGHUP, &SigAct, &OldSigAct);
     324
     325    /* First fork, to become independent process. */
     326    pid_t pid = fork();
     327    if (pid == -1)
     328        return RTErrConvertFromErrno(errno);
     329    if (pid != 0)
     330    {
     331        /* Parent exits, no longer necessary. Child creates gets reparented
     332         * to the init process. */
     333        exit(0);
     334    }
     335
     336    /* Create new session, fix up the standard file descriptors and the
     337     * current working directory. */
     338    pid_t newpgid = setsid();
     339    int SavedErrno = errno;
     340    if (rcSigAct != -1)
     341        sigaction(SIGHUP, &OldSigAct, NULL);
     342    if (newpgid == -1)
     343        return RTErrConvertFromErrno(SavedErrno);
     344
     345    if (!fNoClose)
     346    {
     347        /* Open stdin(0), stdout(1) and stderr(2) as /dev/null. */
     348        int fd = open("/dev/null", O_RDWR);
     349        if (fd == -1) /* paranoia */
     350        {
     351            close(STDIN_FILENO);
     352            close(STDOUT_FILENO);
     353            close(STDERR_FILENO);
     354            fd = open("/dev/null", O_RDWR);
     355        }
     356        if (fd != -1)
     357        {
     358            dup2(fd, STDIN_FILENO);
     359            dup2(fd, STDOUT_FILENO);
     360            dup2(fd, STDERR_FILENO);
     361            if (fd > 2)
     362                close(fd);
     363        }
     364    }
     365
     366    if (!fNoChDir)
     367        chdir("/");
     368
     369    /* Second fork to lose session leader status. */
     370    pid = fork();
     371    if (pid == -1)
     372        return RTErrConvertFromErrno(errno);
     373    if (pid != 0)
     374    {
     375        /* Write the pid file, this is done in the parent, before exiting. */
     376        if (fdPidfile != -1)
     377        {
     378            char szBuf[256];
     379            size_t cbPid = RTStrPrintf(szBuf, sizeof(szBuf), "%d\n", pid);
     380            write(fdPidfile, szBuf, cbPid);
     381            close(fdPidfile);
     382        }
     383        exit(0);
     384    }
     385
     386    return VINF_SUCCESS;
     387}
     388
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette