[dm-devel] pidfile doesn't stop multiple multipathd processes from running.

Benjamin Marzinski bmarzins at redhat.com
Tue Apr 19 22:37:54 UTC 2005


The current pidfile implementation doesn't stop multiple multipathd processes
from running. Running
# while true; do multipthd; done
happily makes tons of them.

The attached patch, against multipath-tools-0.4.4-pre15, fixes this.

-Ben
-------------- next part --------------
diff -urN multipath-tools-0.4.4-pre15/multipathd/pidfile.c multipath-tools-pidfile-fix/multipathd/pidfile.c
--- multipath-tools-0.4.4-pre15/multipathd/pidfile.c	2005-03-31 09:59:45.000000000 -0600
+++ multipath-tools-pidfile-fix/multipathd/pidfile.c	2005-04-19 16:11:54.000000000 -0500
@@ -19,79 +19,68 @@
 */
 
 #include <sys/types.h> /* for pid_t */
+#include <sys/stat.h>  /* for open */
 #include <signal.h>    /* for kill() */
 #include <errno.h>     /* for ESHRC */
 #include <stdio.h>     /* for f...() */
 #include <string.h>    /* for memset() */
 #include <stdlib.h>    /* for atoi() */
 #include <unistd.h>    /* for unlink() */
-
+#include <fcntl.h>     /* for fcntl() */
 #include <debug.h>
 
 #include "pidfile.h"
 
-/* Check if a process exists. */
-static int process_exists(pid_t pid)
-{
-	if (pid > 0)
-		return (kill(pid, 0) == 0 || errno != ESRCH);
-	return 0;
-}
-
-/* Return the pid in a pidfile, or return 0 
- * if the process or pidfile does not exist. */
-static pid_t pidfile_pid(const char *pidFile)
-{
-	FILE *f;
-	char pidstr[20];
-	unsigned ret;
-
-	memset(pidstr, 0, sizeof(pidstr));
-
-	if (!(f = fopen(pidFile, "r"))) {
-		return 0;
-	}
-	if (fread(pidstr, sizeof(char), sizeof(pidstr)-1, f) <= 0) {
-		goto noproc;
-	}
-	ret = atoi(pidstr);
-	
-	if (!process_exists((pid_t)ret)) {
-		goto noproc;
-	}
-	fclose(f);
-	return (pid_t)ret;
-
-noproc:
-	fclose(f);
-	unlink(pidFile);
-	return 0;
-}
-
 int pidfile_create(const char *pidFile, pid_t pid)
 {
-	FILE *f;
 	char buf[20];
-	pid_t oldpid;
-
-	oldpid = pidfile_pid(pidFile);
+	struct flock lock;
+	int fd, value;
 
-	if (oldpid != 0) {
-		condlog(0, "File [%s] exists and process id [%d] is running.", 
-			pidFile, (int)pid);
-		return 1;
-	}
-	if (!(f = fopen(pidFile, "w"))) {
+	if((fd = open(pidFile, O_WRONLY | O_CREAT,
+		       (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) < 0) {
 		condlog(0, "Cannot open pidfile [%s], error was [%s]",
 			pidFile, strerror(errno));
 		return 1;
 	}
+	lock.l_type = F_WRLCK;
+	lock.l_start = 0;
+	lock.l_whence = SEEK_SET;
+	lock.l_len = 0;
+
+	if (fcntl(fd, F_SETLK, &lock) < 0) {
+		if (errno != EACCES && errno != EAGAIN)
+			condlog(0, "Cannot lock pidfile [%s], error was [%s]",
+				pidFile, strerror(errno));
+		else
+			condlog(0, "process is already running");
+		goto fail;
+	}
+	if (ftruncate(fd, 0) < 0) {
+		condlog(0, "Cannot truncate pidfile [%s], error was [%s]",
+			pidFile, strerror(errno));
+		goto fail;
+	}
 	memset(buf, 0, sizeof(buf));
 	snprintf(buf, sizeof(buf)-1, "%u", pid);
-	fwrite(buf, sizeof(char), strlen(buf), f);
-	fflush(f);
-	fclose(f);
-
+	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+		condlog(0, "Cannot write pid to pidfile [%s], error was [%s]",
+			pidFile, strerror(errno));
+		goto fail;
+	}
+	if ((value = fcntl(fd, F_GETFD, 0)) < 0) {
+		condlog(0, "Cannot get close-on-exec flag from pidfile [%s], "
+			"error was [%s]", pidFile, strerror(errno));
+		goto fail;
+	}
+	value |= FD_CLOEXEC;
+	if (fcntl(fd, F_SETFD, value) < 0) {
+		condlog(0, "Cannot set close-on-exec flag from pidfile [%s], "
+			"error was [%s]", pidFile, strerror(errno));
+		goto fail;
+	}
 	return 0;
+fail:
+	close(fd);
+	return 1;
 }
-


More information about the dm-devel mailing list