Bug#35117: --daemonize option for start-stop-daemon [PATCH]
Package: dpkg
Severity: wishlist
Hello world,
I've been having some problems recently trying to get the pcmcia utilities
to do something I wanted, and ended up needing some way of daemonizing
a program that wasn't written to be a daemon (ie, a more thorough version
of "./foo &").
start-stop-daemon seemed the obvious thing to use, but unfortunately it
didn't do anything of the sort. So I added the following:
diff -rub dpkg-1.4.0.33/scripts/start-stop-daemon.c dpkg-1.4.0.33.new/scripts/start-stop-daemon.c
--- dpkg-1.4.0.33/scripts/start-stop-daemon.c Tue Sep 15 02:45:49 1998
+++ dpkg-1.4.0.33.new/scripts/start-stop-daemon.c Sat Mar 27 12:20:53 1999
@@ -30,6 +30,7 @@
static int exitnodo = 1;
static int start = 0;
static int stop = 0;
+static int daemonize = 0;
static int signal_nr = 15;
static const char *signal_str = NULL;
static int user_id = -1;
@@ -133,6 +134,7 @@
-a|--startas <pathname> program to start (default is <executable>)\n\
-t|--test test mode, don't do anything\n\
-o|--oknodo exit status 0 (not 1) if nothing done\n\
+ -d|--daemonize daemonize program\n\
-q|--quiet be more quiet\n\
-v|--verbose be more verbose\n\
\n\
@@ -204,6 +206,7 @@
{ "signal", 1, NULL, 's'},
{ "test", 0, NULL, 't'},
{ "user", 1, NULL, 'u'},
+ { "daemonize", 0, NULL, 'd'},
{ "verbose", 0, NULL, 'v'},
{ "exec", 1, NULL, 'x'},
{ NULL, 0, NULL, 0}
@@ -211,7 +214,7 @@
int c;
for (;;) {
- c = getopt_long(argc, argv, "HKSVa:n:op:qs:tu:vx:",
+ c = getopt_long(argc, argv, "HKSVa:n:op:qs:tu:dvx:",
longopts, (int *) 0);
if (c == -1)
break;
@@ -252,6 +255,9 @@
case 'u': /* --user <username>|<uid> */
userspec = optarg;
break;
+ case 'd': /* --daemonize */
+ daemonize = 1;
+ break;
case 'v': /* --verbose */
quietmode = -1;
break;
@@ -476,6 +482,47 @@
if (quietmode < 0)
printf("Starting %s...\n", startas);
*--argv = startas;
+
+ if (daemonize) {
+ int child, child2;
+ switch(child = fork()) {
+ case -1: /* failed */
+ fatal("fork() failed");
+ case 0: /* child */
+ {
+ int i;
+ waitpid( getppid(), NULL, 0 );
+ setsid();
+ chdir("/");
+ for ( i = 0; i < 256; i++ ) close(i);
+ switch(child2 = fork()) {
+ case -1: /* failed */
+ kill(child, 9);
+ fatal("fork() failed");
+ case 0: /* child */
+ break;
+ default:
+ {
+ if (pidfile) {
+ FILE *pf = fopen(pidfile, "w");
+ fprintf(pf, "%d\n", child2);
+ fclose(pf);
+ }
+ wait(NULL);
+ if (pidfile) {
+ remove(pidfile);
+ }
+ exit(0);
+ }
+ }
+
+ break;
+ }
+ default:
+ exit(0);
+ }
+ }
+
execv(startas, argv);
fatal("Unable to start %s: %s", startas, strerror(errno));
}
The executive summary is that this adds a --daemonize option so you can
say:
start-stop-daemon --daemonize --start ./foo -- args
and have the program ./foo which doesn't normally detach itself or
anything, become properly daemonized.
In a pstree it looks like:
init-+-...
|-start-stop-daem---foo
...
Killing foo causes start-stop-daemon to die also. (see the wait() above)
If you add a --pidfile option, start-stop-daemon will create a pidfile
containing the process id of "foo", which will get rm'ed when foo dies.
It will also get rm'ed when foo is killed with extreme prejudice (-9'ed)
which isn't what would normally happen. C'est la vie.
Anyway. This seems appropriate for start-stop-daemon (since the whole idea
of it is to start a daemon), it works, it's useful, and it's not too
complicated. If this could be officially incorporated into dpkg it'd be
cool.
Thanks in advance.
Cheers,
aj
--
Anthony Towns <aj@humbug.org.au> <http://azure.humbug.org.au/~aj/>
I don't speak for anyone save myself. PGP encrypted mail preferred.
``Like the ski resort of girls looking for husbands and husbands looking
for girls, the situation is not as symmetrical as it might seem.''
Reply to: