changeset 7982:140d9f439c0f HEAD

maildirlock: Previous implementation wasn't usable - redesigned.
author Timo Sirainen <tss@iki.fi>
date Tue, 08 Jul 2008 21:46:35 +0530
parents bb9d3aabcb61
children ba581bed8cc7
files src/util/maildirlock.c
diffstat 1 files changed, 39 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/util/maildirlock.c	Tue Jul 08 21:11:23 2008 +0530
+++ b/src/util/maildirlock.c	Tue Jul 08 21:46:35 2008 +0530
@@ -8,6 +8,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <signal.h>
 
 static struct dotlock_settings dotlock_settings = {
@@ -21,9 +22,11 @@
 };
 
 static struct ioloop *ioloop;
+static bool success = FALSE;
 
-static void sig_die(int signo ATTR_UNUSED, void *context ATTR_UNUSED)
+static void sig_die(int signo, void *context ATTR_UNUSED)
 {
+	success = signo == SIGTERM;
 	io_loop_stop(ioloop);
 }
 
@@ -34,6 +37,7 @@
 	dotlock_settings.use_excl_lock = getenv("DOTLOCK_USE_EXCL") != NULL;
 	dotlock_settings.nfs_flush = getenv("MAIL_NFS_STORAGE") != NULL;
 
+	path = t_strconcat(path, "/" MAILDIR_UIDLIST_NAME, NULL);
 	return file_dotlock_create(&dotlock_settings, path, 0, dotlock_r);
 }
 
@@ -41,23 +45,49 @@
 {
 	struct dotlock *dotlock;
 	unsigned int timeout;
-
-	lib_init();
-	ioloop = io_loop_create();
+	pid_t pid, parent_pid;
 
 	if (argc != 3) {
-		printf("Usage: maildirlock <path> <timeout>\n"
-		       " - SIGTERM will release the lock.\n");
+		fprintf(stderr, "Usage: maildirlock <path> <timeout>\n"
+			" - SIGTERM will release the lock.\n");
+		return 1;
+	}
+	parent_pid = getpid();
+
+	pid = fork();
+	if (pid == (pid_t)-1) {
+		fprintf(stderr, "fork() failed: %m");
 		return 1;
 	}
 
+	/* call lib_init() only after fork so that PID gets set correctly */
+	lib_init();
+	ioloop = io_loop_create();
+	lib_signals_init();
+	lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
+	lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
+	lib_signals_set_handler(SIGCHLD, TRUE, sig_die, NULL);
+
+	if (pid != 0) {
+		/* master - wait for the child process to finish locking */
+		io_loop_run(ioloop);
+		if (!success)
+			return 1;
+		printf("%s", dec2str(pid));
+		return 0;
+	}
+
+	/* child process - stdout has to be closed so that caller knows when
+	   to stop reading it. */
+	dup2(STDERR_FILENO, STDOUT_FILENO);
+
 	timeout = strtoul(argv[2], NULL, 10);
 	if (maildir_lock(argv[1], timeout, &dotlock) <= 0)
 		return 1;
 
-	lib_signals_init();
-	lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
-	lib_signals_set_handler(SIGTERM, TRUE, sig_die, NULL);
+	/* locked - send a  */
+	if (kill(parent_pid, SIGTERM) < 0)
+		i_fatal("kill(parent, SIGTERM) failed: %m");
 	io_loop_run(ioloop);
 
 	file_dotlock_delete(&dotlock);