]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fix autoexpunge locking to actually work correctly.
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Fri, 3 Feb 2017 17:40:54 +0000 (19:40 +0200)
committerGitLab <gitlab@git.dovecot.net>
Sat, 4 Feb 2017 13:02:56 +0000 (15:02 +0200)
It wasn't actually skipping the autoexpunging if the lock already existed.
It autoexpunged anyway.

src/lib-storage/mail-autoexpunge.c

index 5b0b20db648247a8f77c8d1e174fe76c85dbf93e..b8f5aa8adadb6fe8a14f846b19458fd414d5b9f7 100644 (file)
@@ -17,7 +17,7 @@ struct mailbox_autoexpunge_lock {
        int fd;
 };
 
-static void mailbox_autoexpunge_lock(struct mail_user *user,
+static bool mailbox_autoexpunge_lock(struct mail_user *user,
                                     struct mailbox_autoexpunge_lock *lock)
 {
        struct file_create_settings lock_set;
@@ -25,13 +25,16 @@ static void mailbox_autoexpunge_lock(struct mail_user *user,
        const char *home, *error;
        int ret;
 
+       if (lock->fd != -1)
+               return TRUE;
+
        /* Try to lock the autoexpunging. If the lock already exists, another
           process is already busy with expunging, so we don't have to do it.
           The easiest place where to store the lock file to is the home
           directory, but allow autoexpunging to work even if we can't get
           it. The lock isn't really required; it 1) improves performance
           so that multiple processes won't do the same work unnecessarily,
-          and 2) it helps to avoid duplicates mails being added with
+          and 2) it helps to avoid duplicate mails being added with
           lazy_expunge. */
        if ((ret = mail_user_get_home(user, &home)) > 0) {
                const struct mail_storage_settings *mail_set =
@@ -42,12 +45,16 @@ static void mailbox_autoexpunge_lock(struct mail_user *user,
                lock->fd = file_create_locked(lock->path, &lock_set,
                                              &lock->lock, &created, &error);
                if (lock->fd == -1) {
-                       if (errno != EAGAIN && errno != ENOENT)
+                       if (errno == EAGAIN)
+                               return FALSE;
+                       if (errno != ENOENT)
                                i_error("autoexpunge: Couldn't lock %s: %s", lock->path, error);
+                       return TRUE;
                }
        } else if (ret == 0) {
                i_warning("autoexpunge: User has no home directory, can't lock");
        }
+       return TRUE;
 }
 
 static int
@@ -174,7 +181,7 @@ mailbox_autoexpunge_wildcards(struct mail_namespace *ns,
        }
 }
 
-static void
+static bool
 mail_namespace_autoexpunge(struct mail_namespace *ns,
                           struct mailbox_autoexpunge_lock *lock)
 {
@@ -182,14 +189,15 @@ mail_namespace_autoexpunge(struct mail_namespace *ns,
        const char *vname;
 
        if (!array_is_created(&ns->set->mailboxes))
-               return;
+               return TRUE;
 
        array_foreach(&ns->set->mailboxes, box_set) {
                if ((*box_set)->autoexpunge == 0 &&
                    (*box_set)->autoexpunge_max_mails == 0)
                        continue;
 
-               mailbox_autoexpunge_lock(ns->user, lock);
+               if (!mailbox_autoexpunge_lock(ns->user, lock))
+                       return FALSE;
 
                if (strpbrk((*box_set)->name, "*?") != NULL)
                        mailbox_autoexpunge_wildcards(ns, *box_set);
@@ -203,6 +211,7 @@ mail_namespace_autoexpunge(struct mail_namespace *ns,
                                                (*box_set)->autoexpunge_max_mails);
                }
        }
+       return TRUE;
 }
 
 void mail_user_autoexpunge(struct mail_user *user)
@@ -211,8 +220,10 @@ void mail_user_autoexpunge(struct mail_user *user)
        struct mail_namespace *ns;
 
        for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-               if (ns->alias_for == NULL)
-                       mail_namespace_autoexpunge(ns, &lock);
+               if (ns->alias_for == NULL) {
+                       if (!mail_namespace_autoexpunge(ns, &lock))
+                               break;
+               }
        }
        if (lock.fd != -1) {
                i_unlink(lock.path);