monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Monotone-devel] daemon support


From: Ralf S. Engelschall
Subject: Re: [Monotone-devel] daemon support
Date: Tue, 11 Sep 2007 13:44:27 +0200
User-agent: Mutt/1.5.16 OpenPKG/CURRENT (2007-06-09)

On Mon, Sep 10, 2007, Ben Walton wrote:

> I just synced a branch called nvm.daemon-support.  All tests are
> passing on my tree, but I've only got Ubuntu Feisty to test on right
> now.  I hope that someone can build/test it on more platforms (windows
> would be especially helpful).
>
> Let me know if you can help out.

I've not built the sources on your branch, but in the commit notify
mails I see you are just calling the 4.4BSD function daemon(3).
Unfortunaely, IMHO this function is not portable enough for Monotone.

You at least need some Autoconf glue for checking its availability
and provide --daemon only if daemon(3) is available or (my personal
preference) provide at least an own Unix fallback implementation of
daemon(3).

I append you a possible fallback implementation of daemon(3) which I've
created some years ago based on STEVENS and related resources. Feel free
to take it over into Monotone's code base under the GPL if you wish.

Also, for Windows I guess daemon(3) also doesn't exist, but I'm a
Unix-only hacker and have no clue about the Windows APIs and how it can
be emulated under Windows...

                                       Ralf S. Engelschall
                                       address@hidden
                                       www.engelschall.com

/*
**  my_daemon.c -- daemonize current process, fallback for daemon(3)
**  Copyright (c) 1999-2005 Ralf S. Engelschall <address@hidden>
*/

#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

int my_daemon(int nochdir, int noclose)
{
    int fd;
    int rc;

    /* ignore tty related signals */
#ifdef  SIGTTOU
    signal(SIGTTOU, SIG_IGN);
#endif
#ifdef  SIGTTIN
    signal(SIGTTIN, SIG_IGN);
#endif
#ifdef  SIGTSTP
    signal(SIGTSTP, SIG_IGN);
#endif

    /* fork so the parent can exit, this returns control to the command line
       or shell invoking your program. This step is required so that the new
       process is guaranteed not to be a process group leader (The next step,
       setsid, would fail if you're a process group leader). */
    rc = fork();
    switch (rc) {
        case -1: return -1;
        case  0: break;
        default: _exit(0); /* exit original process */
    }

    /* setsid to become a process group and session group leader. Since a
       controlling terminal is associated with a session, and this new session
       has not yet acquired a controlling terminal our process now has no
       controlling terminal, which is a Good Thing for daemons. */
#ifdef HAVE_SETSID
    if (setsid() == -1)
        return -1;
#else
    if (setpgid(0, getpid()) == -1)
        return -1;
#ifndef _PATH_TTY
#define _PATH_TTY "/dev/tty"
#endif
    if ((fd = open(_PATH_TTY, O_RDWR)) == -1)
        return -1;
    ioctl(fd, TIOCNOTTY, NULL);
    close(fd);
#endif

    /* fork again so the parent (the session group leader) can exit. This
       means that we, as a non-session group leader, can never regain a
       controlling terminal. */
    rc = fork();
    switch (rc) {
        case -1: return -1;
        case  0: break;
        default: _exit(0); /* exit original process */
    }

    /* change to root directory ensure that our process doesn't keep
       any directory in use. Failure to do this could make it so that
       an administrator couldn't unmount a filesystem, because it was
       our current directory. [Equivalently, we could change to any
       directory containing files important to the daemon's operation.] */
    if (!nochdir)
        chdir("/");

    /* give us complete control over the permissions of anything we
       write. We don't know what umask we may have inherited.
       [This step is optional] */
    umask(0);

    /* close fds 0, 1, and 2. This releases the standard in, out, and
       error we inherited from our parent process. We have no way of
       knowing where these fds might have been redirected to. */
    if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
        dup2(fd, STDIN_FILENO);
        dup2(fd, STDOUT_FILENO);
        dup2(fd, STDERR_FILENO);
        if (fd > 2)
            close(fd);
    }

    return 0;
}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]