VirtualBox

Changeset 11337

Show
Ignore:
Timestamp:
08/11/08 17:15:13 (3 months ago)
Author:
vboxsync
Message:

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

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/include/iprt/process.h

    r8245 r11337  
    227227RTR3DECL(char *) RTProcGetExecutableName(char *pszExecName, size_t cchExecName); 
    228228 
     229/** 
     230 * Daemonize the current process, making it a background process. The current 
     231 * process will exit if daemonizing is successful. 
     232 * 
     233 * @returns iprt status code. 
     234 * @param   fNoChDir    Pass false to change working directory to "/". 
     235 * @param   fNoClose    Pass false to redirect standard file streams to the null device. 
     236 * @param   pszPidfile  Path to a file to write the process id of the daemon 
     237 *                      process to. Daemonizing will fail if this file already 
     238 *                      exists or cannot be written. May be NULL. 
     239 */ 
     240RTR3DECL(int)   RTProcDaemonize(bool fNoChDir, bool fNoClose, const char *pszPidfile); 
     241 
    229242#endif /* IN_RING3 */ 
    230243 
  • 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 

© 2008 Sun Microsystems, Inc.
ContactPrivacy policy