From 4e3e50374f74af24b35524a994af85a080c29722 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Tue, 8 Jul 2008 21:46:35 +0530 Subject: [PATCH] maildirlock: Previous implementation wasn't usable - redesigned. --HG-- branch : HEAD --- src/util/maildirlock.c | 46 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/src/util/maildirlock.c b/src/util/maildirlock.c index 5691f2cfcf..203cb176da 100644 --- a/src/util/maildirlock.c +++ b/src/util/maildirlock.c @@ -8,6 +8,7 @@ #include #include +#include #include 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 \n" - " - SIGTERM will release the lock.\n"); + fprintf(stderr, "Usage: maildirlock \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); -- 2.47.3