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

Bug#35117: daemonize option for start-stop-daemon [PATCH]



On Sat, Mar 27, 1999 at 12:13:47AM -0800, Joey Hess wrote:
> I think this patch would make a lot more sense if you made start-stop-daemon
> not hang around as a daemon itself, wasting memory for very little good
> reason.

Well, it's only 10kB, and it does spend all its time wait()'ing
so should stay comfortably swapped out if memory gets that tight. I
(probably obviously) wasn't really too concerned. Admittedly, it doubled
the footprint of the program I was using, but still...

Anyway. The only reason it hangs around is to delete the pid file.

It might be possible to have ssd remove the pidfile when it was --stop'ing
the process, but then you need to work out when the process is actually
stopped, as rm'ing the pidfile when you're just SIGHUPing the daemon
would be bad.

And of course, you could always just expect people to rm the pidfile
themselves, or just get them to live with it hanging around, but those
are fairly ugly solutions.

Hmmm. I guess something like:

         if (quietmode < 0 && killed) {
                 printf("Stopped %s (pid", what);
                 for (p = killed; p; p = p->next)
                         printf(" %d", p->pid);
                 printf(").\n");
         }
+
+        if (pidfile) {
+                if (!killed) { 
+                        /* there was no such process in the first place */
+                        unlink(pidfile);
+                } else if ( kill(killed->pid,0) < 0 && errno == ESRCH) {
+                        /* there was such a process, and it's died now */
+                        unlink(pidfile);
+                }
+        }

could work. I can't see any reason off hand to worry about whether the
pidfile actually exists, just unlinking it seems fine.

I s'pose this also has the benefit that it'd clean up after buggy daemons
that make pidfiles but don't remove them themselves.

It seems like it would have problems if the daemonized program took
a while to shutdown, though.

I'm not overly concerned which way this is done, personally.

FWIW, that makes the patch:

--- 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 20:28:05 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;
@@ -404,12 +410,13 @@
 		sprintf(what, "process(es) owned by `%s'", userspec);
 	else
 		fatal("internal error, please report");
-
+#if 0
 	if (!found) {
 		if (quietmode <= 0)
 			printf("No %s found running; none killed.\n", what);
 		exit(exitnodo);
 	}
+#endif
 	for (p = found; p; p = p->next) {
 		if (testmode)
 			printf("Would send signal %d to %d.\n",
@@ -426,6 +433,16 @@
 			printf(" %d", p->pid);
 		printf(").\n");
 	}
+        
+        if (pidfile) {
+                if (!killed) {
+                        /* there was no such process in the first place */
+                        unlink(pidfile);
+                } else if ( kill(killed->pid,0) < 0 && errno == ESRCH) {
+                        /* there was such a process, and it's died now */
+                        unlink(pidfile);
+                }
+        }
 }
 
 
@@ -476,6 +493,35 @@
 	if (quietmode < 0)
 		printf("Starting %s...\n", startas);
 	*--argv = startas;
+
+	if (daemonize) {
+		int child, child2;
+		FILE *pf;
+		if (pidfile) {
+			pf = fopen(pidfile, "w");
+			if (!pf) fatal("couldn't open pid file");
+		}
+		switch(child = fork()) {
+		    case -1: /* failed */
+			fatal("fork() failed");
+		    case 0: /* child */
+		    {
+			int i;
+			if (pidfile) {
+				fprintf(pf, "%d\n", getpid());
+				fclose(pf);
+			}
+			waitpid( getppid(), NULL, 0 );
+			setsid();
+			chdir("/");
+			for ( i = 0; i < 256; i++ ) close(i);
+			break;
+		    }
+		    default:
+			exit(0);
+		}
+	}
+
 	execv(startas, argv);
 	fatal("Unable to start %s: %s", startas, strerror(errno));
 }

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.''

Attachment: pgpAn3JT2dDmn.pgp
Description: PGP signature


Reply to: