[Top][All Lists]
[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;
}