[dovecot-cvs] dovecot/src/lib file-lock.c,1.1,1.2 file-lock.h,1.1,1.2 lib-signals.c,1.2,1.3

cras at procontrol.fi cras at procontrol.fi
Thu Oct 24 00:41:37 EEST 2002


Update of /home/cvs/dovecot/src/lib
In directory danu:/tmp/cvs-serv24024/lib

Modified Files:
	file-lock.c file-lock.h lib-signals.c 
Log Message:
file_wait_lock() now takes timeout-parameter so one badly behaving process
won't start creating tons of lock-waiting processes.



Index: file-lock.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/file-lock.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- file-lock.c	14 Sep 2002 11:09:42 -0000	1.1
+++ file-lock.c	23 Oct 2002 20:41:35 -0000	1.2
@@ -26,6 +26,19 @@
 #include "lib.h"
 #include "file-lock.h"
 
+#include <signal.h>
+
+static int got_alarm = FALSE;
+
+static void sig_alarm(int signo __attr_unused__)
+{
+	got_alarm = TRUE;
+
+	/* we need fcntl() to stop with EINTR */
+	if (raise(SIGHUP) < 0)
+		i_fatal("kill(): %m");
+}
+
 static int file_lock(int fd, int wait_lock, int lock_type)
 {
 	struct flock fl;
@@ -41,6 +54,11 @@
 
 		if (errno != EINTR)
 			return -1;
+
+		if (got_alarm) {
+			errno = EAGAIN;
+			return 0;
+		}
 	}
 
 	return 1;
@@ -48,10 +66,56 @@
 
 int file_try_lock(int fd, int lock_type)
 {
+        got_alarm = FALSE;
 	return file_lock(fd, FALSE, lock_type);
 }
 
-int file_wait_lock(int fd, int lock_type)
+int file_wait_lock(int fd, int lock_type, unsigned int timeout __attr_unused__)
 {
-	return file_lock(fd, TRUE, lock_type);
+#ifdef HAVE_SIGACTION
+	struct sigaction act;
+#endif
+	int ret;
+
+	got_alarm = FALSE;
+
+	if (timeout > 0 && lock_type != F_UNLCK) {
+#ifdef HAVE_SIGACTION
+		if (sigemptyset(&act.sa_mask) < 0)
+			i_fatal("sigemptyset(): %m");
+		act.sa_flags = 0;
+		act.sa_handler = sig_alarm;
+
+		while (sigaction(SIGALRM, &act, NULL) < 0) {
+			if (errno != EINTR)
+				i_fatal("sigaction(): %m");
+		}
+#else
+		/* at least Linux blocks raise(SIGHUP) inside SIGALRM
+		   handler if it's added with signal().. sigaction() should
+		   be pretty much everywhere though, so this code is pretty
+		   useless. */
+#warning file_wait_lock() timeouting may not work
+		signal(SIGALRM, sig_alarm);
+#endif
+
+		alarm(timeout);
+	}
+
+	ret = file_lock(fd, TRUE, lock_type);
+
+	if (timeout > 0 && lock_type != F_UNLCK) {
+		alarm(0);
+
+#ifdef HAVE_SIGACTION
+		act.sa_handler = SIG_DFL;
+		while (sigaction(SIGALRM, &act, NULL) < 0) {
+			if (errno != EINTR)
+				i_fatal("sigaction(): %m");
+		}
+#else
+		signal(SIGALRM, SIG_IGN);
+#endif
+	}
+	return ret;
 }

Index: file-lock.h
===================================================================
RCS file: /home/cvs/dovecot/src/lib/file-lock.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- file-lock.h	14 Sep 2002 11:09:42 -0000	1.1
+++ file-lock.h	23 Oct 2002 20:41:35 -0000	1.2
@@ -4,11 +4,15 @@
 #include <unistd.h>
 #include <fcntl.h>
 
+#define DEFAULT_LOCK_TIMEOUT 120
+
 /* Lock whole file descriptor. Returns 1 if successful, 0 if lock failed,
    or -1 if error. lock_type is F_WRLCK, F_RDLCK or F_UNLCK. */
 int file_try_lock(int fd, int lock_type);
 
-/* Lock whole file descriptor. Returns 1 if successful, or -1 if error. */
-int file_wait_lock(int fd, int lock_type);
+/* Lock whole file descriptor. Returns 1 if successful, 0 if timeout or
+   -1 if error. When returning 0, errno is also set to EAGAIN.
+   NOTE: timeout uses SIGALRM and resets it at the end. */
+int file_wait_lock(int fd, int lock_type, unsigned int timeout);
 
 #endif

Index: lib-signals.c
===================================================================
RCS file: /home/cvs/dovecot/src/lib/lib-signals.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- lib-signals.c	24 Sep 2002 13:53:43 -0000	1.2
+++ lib-signals.c	23 Oct 2002 20:41:35 -0000	1.3
@@ -67,10 +67,14 @@
 	   isn't ignored, or your handler doesn't kill the program,
 	   sigaction() should be used. */
 #ifdef HAVE_SIGACTION
-	sigemptyset(&act.sa_mask);
+	if (sigemptyset(&act.sa_mask) < 0)
+		i_fatal("sigemptyset(): %m");
 	act.sa_flags = 0;
 	act.sa_handler = sig_hup;
-	sigaction(SIGHUP, &act, NULL);
+	while (sigaction(SIGHUP, &act, NULL) < 0) {
+		if (errno != EINTR)
+			i_fatal("sigaction(): %m");
+	}
 #else
         signal(SIGHUP, sig_hup);
 #endif




More information about the dovecot-cvs mailing list