Hi Javier, 

Please find attached a revised patch that I propose for this NMU. It's a
bit more invasive that what I would usually feel comfortable including
in an NMU, so I won't upload without your approval. 

On Tue, 2006-02-14 at 12:42 +0100, Javier Fernández-Sanguino Peña wrote:

> Why doesn't --make-pidfile work?

start-stop-daemon creates the pidfile, but portreserve forks after this
as it becomes a daemon. The pidfile then points to the non-existent
parent process.

> * /var/run should not be harcoded, it should be #DEFINEd (that way the
>   patch is usable for other distros)

Agreed, fixed.

> * it should return an integer to determine if it is succesful or not (the
>   main program could, or could not, care about the pid file
>   creation and check the return value)

Agreed, fixed.

> * there's a buffer overflow if 'fname' is longer than 512 chars. buf should
>   *not* be of a static size

There is no buffer overflow, the worst would be the pidfile name is
truncated, we are using snprintf not sprintf. However I have added
further error checking to handle the (unlikely) case of the pidfile name
exceeding 512 characters.

Note that that case is (and was in the previous patch) not possible in
this instance of the code as do_pid is only ever called with NULL as its
first argument.

> * it should refuse to run (or create a pidfile) if the pidfile already
>   exists.
<snip>
Agreed - improved pidfile handling is now in the patch.

> I suggest you reuse a pidfile creation function from some other tested
> program, there should be plenty of examples around.

Unfortunately most are heavily integrated with the specified application
and its error logging routines etc. This is why we originally developed
the put_pid function that I included in the original patch, it acts as a
library function within my group of friends. I've now updated and
improved it based on your (much appreciated) comments on its
deficiencies.

> I don't like the patch to portreserve.c and I object to this NMU. You *can*
> NMU, however, to include the changes to the init.d script.

Are you happier with this revised patch?

Thanks for your time. 

Regards

-- 
Matt Brown
[EMAIL PROTECTED]
Mob +64 21 611 544 www.mattb.net.nz
diff -ur portreserve-0.0.0/debian/changelog portreserve-0.0.0-matt/debian/changelog
--- portreserve-0.0.0/debian/changelog	2006-02-12 11:07:31.000000000 +0000
+++ portreserve-0.0.0-matt/debian/changelog	2006-02-15 12:04:55.000000000 +0000
@@ -1,3 +1,16 @@
+portreserve (0.0.0-2.1) unstable; urgency=low
+
+  * Non-maintainer upload
+  * Fixed minor init script bugs (Closes: #352103)
+    - Use -z instead of -n to test list of service files
+    - Use $NAME instead of the undefined $prog in the pidfile name
+  * Reworked portreserve pidfile handling
+    - Check for existance of pidfile on startup, fail if already running
+    - Create pidfile on startup
+    - Remove pidfile when program exits cleanly
+  
+ -- Matt Brown <[EMAIL PROTECTED]>  Thu, 16 Feb 2006 01:02:03 +1300
+
 portreserve (0.0.0-2) unstable; urgency=low
 
   * Added xmlto to Build-Depends (Closes: #337848)
diff -ur portreserve-0.0.0/debian/portreserve.init portreserve-0.0.0-matt/debian/portreserve.init
--- portreserve-0.0.0/debian/portreserve.init	2006-02-12 11:07:31.000000000 +0000
+++ portreserve-0.0.0-matt/debian/portreserve.init	2006-02-15 11:43:34.000000000 +0000
@@ -11,7 +11,7 @@
 test -f $DAEMON || exit 0
 
 NAME=`basename $DAEMON`
-PIDFILE=/var/run/$prog.pid
+PIDFILE=/var/run/$NAME.pid
 
 running()
 {
@@ -22,8 +22,8 @@
     # No pid, probably no daemon present
     [ -z "$pid" ] && return 1
     [ ! -d /proc/$pid ] &&  return 1
-    cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
-
+    cmdline=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
+    cmd=`basename $cmdline`
     [ "$cmd" != "$NAME" ] &&  return 1
     return 0
 }
@@ -36,7 +36,7 @@
 	if [ ! -d /etc/portreserve ] ; then
 		return 1
 	fi
-	if [ -n "`find /etc/portreserve \! -name "*~" -a \! -name "*.*" -type f`" ] ; then
+	if [ -z "`find /etc/portreserve \! -name "*~" -a \! -name "*.*" -type f`" ] ; then
 		return 1
 	fi
 	return 0
Only in portreserve-0.0.0-matt/: .deps
Only in portreserve-0.0.0: portreserve.spec
diff -ur portreserve-0.0.0/src/portreserve.c portreserve-0.0.0-matt/src/portreserve.c
--- portreserve-0.0.0/src/portreserve.c	2003-09-03 14:12:52.000000000 +0000
+++ portreserve-0.0.0-matt/src/portreserve.c	2006-02-15 12:06:27.000000000 +0000
@@ -64,7 +64,13 @@
 # include <unistd.h>
 #endif
 
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #define UNIX_SOCKET "/var/run/portreserve/socket"
+#define PIDFILE_DIR "/var/run"
 
 struct map {
 	struct map *next;
@@ -265,8 +271,76 @@
 }
 
 int
+do_pid(char *fname, int check, int unlink_pid)
+{
+	char *defname = "portreserve";
+	char buf[512];
+	FILE *fp=NULL;
+	int fd, rv;
+	long int pid;
+    
+	/* Determine pidfile name */
+	if( fname == NULL ) {
+		fname = defname;
+		rv = snprintf( &buf[0], 512, "%s/%s.pid", PIDFILE_DIR, fname );
+	} else {
+		rv = snprintf( &buf[0], 512, "%s", fname );
+	}
+	if (rv >= 512)
+		return -1;
+	if (unlink_pid) {
+		/* Remove the pidfile */
+		unlink(buf);
+		return 0;
+	}
+	if (check) {
+		/* Check if the pidfile already exists */
+		if (access (buf, F_OK) == -1) {
+			return 0;
+		}
+		/* Check it is not stale */
+		fp = fopen(&buf[0], "r");
+		if (!fp)
+			return -1;
+		if (fscanf(fp, "%ld", &pid)!=1)
+			return -1;
+		if (kill(pid,0)==0 || errno != ESRCH) {
+			/* Process in pidfile exists */
+			return -1;
+		}
+		/* Stale pidfile, ok to overrwite */
+		return 0;
+	}
+	/* Create a new pidfile */
+	fd=creat(&buf[0],0660);
+	if (fd<0) {
+		return -1;
+	}
+	if (snprintf(&buf[0],512,"%i\n",getpid())>=512) {
+		printf("failed to create pid string\n");
+		close(fd);
+		return -1;
+	}
+	if (write(fd,buf,strlen(&buf[0])) != (signed)strlen(&buf[0])) {
+		printf("failed to write pidstring\n");
+		close(fd);
+		return -1;
+	}
+	close(fd);
+	return 0;
+}
+
+void
+handle_sigterm (int sig)
+{
+	do_pid(NULL, 0, 1);
+	exit(0);
+}
+
+int
 main (int argc, char **argv)
 {
+	int rv;
 	const char *p = strrchr (argv[0], '/');
 	if (!p++)
 		p = argv[0];
@@ -278,7 +352,9 @@
 			r += portrelease (argv[i]);
 		return r;
 	}
-
+	
+	signal (SIGTERM, handle_sigterm);
+	
 	if (argc > 1) {
 		if (!strcmp (argv[1], "-d"))
 			debug = 1;
@@ -288,6 +364,9 @@
 			       "what this program does.");
 	}
 
+	if (do_pid(NULL, 1, 0)<0)
+		error(EXIT_FAILURE, errno, "Pidfile already exists!");
+	
 	if (!debug) {
 		switch (fork ()) {
 		case 0:
@@ -302,7 +381,12 @@
 		close (STDOUT_FILENO);
 		close (STDERR_FILENO);
 		setsid ();
+		if (do_pid(NULL, 0, 0)<0)
+			error (EXIT_FAILURE, errno, 
+					"Failed to write pidfile!");
 	}
 
-	return portreserve ();
+	rv = portreserve();
+	do_pid(NULL, 0, 1);
+	return rv;
 }

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to