]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
maildirlock: Previous implementation wasn't usable - redesigned.
authorTimo Sirainen <tss@iki.fi>
Tue, 8 Jul 2008 16:16:35 +0000 (21:46 +0530)
committerTimo Sirainen <tss@iki.fi>
Tue, 8 Jul 2008 16:16:35 +0000 (21:46 +0530)
--HG--
branch : HEAD

src/util/maildirlock.c

index 5691f2cfcff8558d69407464e5feb6d483e8d7e7..203cb176da563773b84cc39ea0976a123b70a47c 100644 (file)
@@ -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 dotlock_settings dotlock_settings = {
 };
 
 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 @@ static int maildir_lock(const char *path, unsigned int timeout,
        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 @@ int main(int argc, const char *argv[])
 {
        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();
 
-       timeout = strtoul(argv[2], NULL, 10);
-       if (maildir_lock(argv[1], timeout, &dotlock) <= 0)
+       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;
+
+       /* locked - send a  */
+       if (kill(parent_pid, SIGTERM) < 0)
+               i_fatal("kill(parent, SIGTERM) failed: %m");
        io_loop_run(ioloop);
 
        file_dotlock_delete(&dotlock);