[3.0] b96c0af Use file locking on SHMFILE to indicate this file is currently in use

Tollef Fog Heen tfheen at varnish-cache.org
Tue Aug 9 11:06:44 CEST 2011


commit b96c0af72e3f58f2bc767c387c8df350f9092f1e
Author: Martin Blix Grydeland <martin at varnish-software.com>
Date:   Tue Jun 14 13:09:56 2011 +0200

    Use file locking on SHMFILE to indicate this file is currently in use
    
    Fixes: #876

diff --git a/bin/varnishd/mgt_shmem.c b/bin/varnishd/mgt_shmem.c
index f28bc9b..4fc905c 100644
--- a/bin/varnishd/mgt_shmem.c
+++ b/bin/varnishd/mgt_shmem.c
@@ -101,6 +101,7 @@
 #include "heritage.h"
 #include "vmb.h"
 #include "vsm.h"
+#include "flopen.h"
 
 #ifndef MAP_HASSEMAPHORE
 #define MAP_HASSEMAPHORE 0 /* XXX Linux */
@@ -125,11 +126,24 @@ vsl_n_check(int fd)
 	struct VSM_head slh;
 	int i;
 	struct stat st;
+	pid_t pid;
 
 	AZ(fstat(fd, &st));
 	if (!S_ISREG(st.st_mode))
 		ARGV_ERR("\tshmlog: Not a file\n");
 
+	/* Test if the SHMFILE is locked by other Varnish */
+	if (fltest(fd, &pid) > 0) {
+		fprintf(stderr,
+			"SHMFILE locked by running varnishd master (pid=%jd)\n",
+			(intmax_t)pid);
+		fprintf(stderr,
+			"(Use unique -n arguments if you want multiple "
+			"instances)\n");
+		exit(2);
+	}
+
+	/* Read owning pid from SHMFILE */
 	memset(&slh, 0, sizeof slh);	/* XXX: for flexelint */
 	i = read(fd, &slh, sizeof slh);
 	if (i != sizeof slh)
@@ -138,15 +152,11 @@ vsl_n_check(int fd)
 		return;
 	if (slh.hdrsize != sizeof slh)
 		return;
-
 	if (slh.master_pid != 0 && !kill(slh.master_pid, 0)) {
-		fprintf(stderr,
-		    "SHMFILE owned by running varnishd master (pid=%jd)\n",
-		    (intmax_t)slh.master_pid);
-		fprintf(stderr,
-		    "(Use unique -n arguments if you want multiple "
-		    "instances.)\n");
-		exit(2);
+		fprintf(stderr, 
+			"WARNING: Taking over SHMFILE marked as owned by "
+			"running process (pid=%jd)\n",
+			(intmax_t)slh.master_pid);
 	}
 }
 
@@ -161,15 +171,20 @@ vsl_buildnew(const char *fn, unsigned size, int fill)
 	int i;
 	unsigned u;
 	char buf[64*1024];
+	int flags;
 
 	(void)unlink(fn);
-	vsl_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0644);
+	vsl_fd = flopen(fn, O_RDWR | O_CREAT | O_EXCL | O_NONBLOCK, 0644);
 	if (vsl_fd < 0) {
 		fprintf(stderr, "Could not create %s: %s\n",
 		    fn, strerror(errno));
 		exit (1);
 	}
-
+	flags = fcntl(vsl_fd, F_GETFL);
+	assert(flags != -1);
+	flags &= ~O_NONBLOCK;
+	AZ(fcntl(vsl_fd, F_SETFL, flags));
+	
 	memset(&slh, 0, sizeof slh);
 	slh.magic = VSM_HEAD_MAGIC;
 	slh.hdrsize = sizeof slh;
@@ -277,7 +292,6 @@ mgt_SHM_Init(const char *l_arg)
 		vsl_n_check(i);
 		(void)close(i);
 	}
-	(void)close(i);
 	vsl_buildnew(VSM_FILENAME, size, fill);
 
 	VSM_head = (void *)mmap(NULL, size,
diff --git a/include/flopen.h b/include/flopen.h
index 4bd0209..e5b6030 100644
--- a/include/flopen.h
+++ b/include/flopen.h
@@ -31,6 +31,9 @@
 #ifndef FLOPEN_H_INCLUDED
 #define FLOPEN_H_INCLUDED
 
+#include <sys/types.h>
+
 int flopen(const char *, int, ...);
+int fltest(int fd, pid_t *pid);
 
 #endif
diff --git a/lib/libvarnish/flopen.c b/lib/libvarnish/flopen.c
index 43882fe..483d8d6 100644
--- a/lib/libvarnish/flopen.c
+++ b/lib/libvarnish/flopen.c
@@ -107,3 +107,27 @@ flopen(const char *path, int flags, ...)
 		return (fd);
 	}
 }
+
+/* Tests if the given fd is locked through flopen
+ * If pid is non-NULL, stores the pid of the process holding the lock there
+ * Returns 1 if the file is locked
+ * Returns 0 if the file is unlocked
+ * Returns -1 on error (and errno)
+ */
+int
+fltest(int fd, pid_t *pid)
+{
+	struct flock lock;
+
+	memset(&lock, 0, sizeof lock);
+	lock.l_type = F_WRLCK;
+	lock.l_whence = SEEK_SET;
+
+	if (fcntl(fd, F_GETLK, &lock) == -1)
+		return (-1);
+	if (lock.l_type == F_UNLCK)
+		return (0);
+	if (pid != NULL)
+		*pid = lock.l_pid;
+	return (1);
+}



More information about the varnish-commit mailing list