Mercurial > dovecot > original-hg > dovecot-1.2
changeset 2941:89ab5c72430d HEAD
lock_method=dotlock doesn't crash anymore while trying to modify cache file.
We didn't previously deal with any fatal errors that fcntl/flock locking
could have given but assumed that the locking succeeded.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 05 Dec 2004 06:10:43 +0200 |
parents | 0e1481357fbb |
children | c7d426f8cb58 |
files | src/lib-index/mail-cache-private.h src/lib-index/mail-cache.c src/lib-index/mail-index-lock.c src/lib-index/mail-index-private.h src/lib-index/mail-transaction-log.c |
diffstat | 5 files changed, 77 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-index/mail-cache-private.h Sun Dec 05 05:42:43 2004 +0200 +++ b/src/lib-index/mail-cache-private.h Sun Dec 05 06:10:43 2004 +0200 @@ -125,6 +125,7 @@ const void *data; size_t mmap_length; struct file_cache *file_cache; + struct dotlock dotlock; const struct mail_cache_header *hdr; struct mail_cache_header hdr_copy;
--- a/src/lib-index/mail-cache.c Sun Dec 05 05:42:43 2004 +0200 +++ b/src/lib-index/mail-cache.c Sun Dec 05 06:10:43 2004 +0200 @@ -299,6 +299,24 @@ i_free(cache); } +static int mail_cache_lock_file(struct mail_cache *cache, int lock_type) +{ + if (cache->index->lock_method != MAIL_INDEX_LOCK_DOTLOCK) { + return mail_index_lock_fd(cache->index, cache->filepath, + cache->fd, lock_type, + MAIL_INDEX_LOCK_SECS); + } + + if (lock_type != F_UNLCK) { + return file_lock_dotlock(cache->filepath, NULL, FALSE, + MAIL_INDEX_LOCK_SECS, 0, + MAIL_INDEX_LOCK_SECS, + NULL, NULL, &cache->dotlock); + } else { + return file_unlock_dotlock(cache->filepath, &cache->dotlock); + } +} + int mail_cache_lock(struct mail_cache *cache) { struct mail_index_view *view; @@ -330,13 +348,9 @@ } for (i = 0; i < 3; i++) { - ret = mail_index_lock_fd(cache->index, cache->fd, F_WRLCK, - MAIL_INDEX_LOCK_SECS); - if (ret <= 0) { - mail_cache_set_syscall_error(cache, - "mail_index_wait_lock_fd()"); + ret = mail_cache_lock_file(cache, F_WRLCK); + if (ret <= 0) break; - } cache->locked = TRUE; if (cache->hdr->file_seq == ext->reset_id) { @@ -414,10 +428,7 @@ mail_cache_update_need_compress(cache); } - if (mail_index_lock_fd(cache->index, cache->fd, F_UNLCK, 0) <= 0) { - mail_cache_set_syscall_error(cache, - "mail_index_wait_lock_fd(F_UNLCK)"); - } + (void)mail_cache_lock_file(cache, F_UNLCK); } struct mail_cache_view *
--- a/src/lib-index/mail-index-lock.c Sun Dec 05 05:42:43 2004 +0200 +++ b/src/lib-index/mail-index-lock.c Sun Dec 05 06:10:43 2004 +0200 @@ -33,10 +33,13 @@ #define MAIL_INDEX_LOCK_WAIT_TIME 120 -int mail_index_lock_fd(struct mail_index *index, int fd, int lock_type, - unsigned int timeout_secs) +int mail_index_lock_fd(struct mail_index *index, const char *path, int fd, + int lock_type, unsigned int timeout_secs) { - if (timeout_secs != 0) alarm(MAIL_INDEX_LOCK_WAIT_TIME); + int ret; + + if (timeout_secs != 0) + alarm(MAIL_INDEX_LOCK_WAIT_TIME); switch (index->lock_method) { case MAIL_INDEX_LOCK_FCNTL: { @@ -50,24 +53,28 @@ fl.l_start = 0; fl.l_len = 0; - if (fcntl(fd, timeout_secs ? F_SETLKW : F_SETLK, &fl) < 0) { - if (timeout_secs == 0 && - (errno == EACCES || errno == EAGAIN)) { - /* locked by another process */ - return 0; - } + ret = fcntl(fd, timeout_secs ? F_SETLKW : F_SETLK, &fl); + if (timeout_secs != 0) alarm(0); + + if (ret == 0) + return 1; - if (errno == EINTR) { - /* most likely alarm hit, meaning we timeouted. - even if not, we probably want to be killed - so stop blocking. */ - errno = EAGAIN; - if (timeout_secs != 0) alarm(0); - return 0; - } + if (timeout_secs == 0 && + (errno == EACCES || errno == EAGAIN)) { + /* locked by another process */ + return 0; } - if (timeout_secs != 0) alarm(0); - return 1; + + if (errno == EINTR) { + /* most likely alarm hit, meaning we timeouted. + even if not, we probably want to be killed + so stop blocking. */ + errno = EAGAIN; + return 0; + } + mail_index_file_set_syscall_error(index, path, + "mail_index_lock_fd()"); + return -1; #endif } case MAIL_INDEX_LOCK_FLOCK: { @@ -88,16 +95,20 @@ break; } - if (flock(fd, operation) < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) { - /* a) locked by another process, - b) timeouted */ - if (timeout_secs != 0) alarm(0); - return 0; - } + ret = flock(fd, operation); + if (timeout_secs != 0) alarm(0); + + if (ret == 0) + return 1; + + if (errno == EWOULDBLOCK || errno == EINTR) { + /* a) locked by another process, + b) timeouted */ + return 0; } - if (timeout_secs != 0) alarm(0); - return 1; + mail_index_file_set_syscall_error(index, path, + "mail_index_lock_fd()"); + return -1; #endif } case MAIL_INDEX_LOCK_DOTLOCK: @@ -160,8 +171,8 @@ } if (lock_type == F_RDLCK || !index->log_locked) { - ret = mail_index_lock_fd(index, index->fd, lock_type, - timeout_secs); + ret = mail_index_lock_fd(index, index->filepath, index->fd, + lock_type, timeout_secs); } else { /* this is kind of kludgy. we wish to avoid deadlocks while trying to lock transaction log, but it can happen if our @@ -177,14 +188,11 @@ so, the workaround for this problem is that we simply try locking once. if it doesn't work, just rewrite the file. hopefully there won't be any other deadlocking issues. :) */ - ret = mail_index_lock_fd(index, index->fd, lock_type, 0); + ret = mail_index_lock_fd(index, index->filepath, index->fd, + lock_type, 0); } - if (ret <= 0) { - if (ret == 0) - return 0; - mail_index_set_syscall_error(index, "mail_index_lock_fd()"); - return -1; - } + if (ret <= 0) + return ret; if (index->lock_type == F_UNLCK) index->lock_id += 2; @@ -369,10 +377,8 @@ if (index->shared_lock_count > 0 && index->lock_method != MAIL_INDEX_LOCK_DOTLOCK) { /* leave ourself shared locked. */ - if (mail_index_lock_fd(index, index->fd, F_RDLCK, 0) <= 0) { - mail_index_file_set_syscall_error(index, - index->copy_lock_path, "mail_index_lock_fd()"); - } + (void)mail_index_lock_fd(index, index->filepath, index->fd, + F_RDLCK, 0); i_assert(index->lock_type == F_WRLCK); index->lock_type = F_RDLCK; } @@ -409,11 +415,8 @@ index->lock_id += 2; index->lock_type = F_UNLCK; if (index->lock_method != MAIL_INDEX_LOCK_DOTLOCK) { - if (mail_index_lock_fd(index, index->fd, - F_UNLCK, 0) < 0) { - mail_index_set_syscall_error(index, - "mail_index_lock_fd()"); - } + (void)mail_index_lock_fd(index, index->filepath, + index->fd, F_UNLCK, 0); } } }
--- a/src/lib-index/mail-index-private.h Sun Dec 05 05:42:43 2004 +0200 +++ b/src/lib-index/mail-index-private.h Sun Dec 05 06:10:43 2004 +0200 @@ -168,8 +168,8 @@ /* Returns 1 if given lock_id is valid, 0 if not. */ int mail_index_is_locked(struct mail_index *index, unsigned int lock_id); -int mail_index_lock_fd(struct mail_index *index, int fd, int lock_type, - unsigned int timeout_secs); +int mail_index_lock_fd(struct mail_index *index, const char *path, int fd, + int lock_type, unsigned int timeout_secs); /* Reopen index file if it has changed. */ int mail_index_reopen_if_needed(struct mail_index *index);
--- a/src/lib-index/mail-transaction-log.c Sun Dec 05 05:42:43 2004 +0200 +++ b/src/lib-index/mail-transaction-log.c Sun Dec 05 06:10:43 2004 +0200 @@ -126,8 +126,8 @@ if (file->log->index->lock_method == MAIL_INDEX_LOCK_DOTLOCK) return mail_transaction_log_file_dotlock(file); - ret = mail_index_lock_fd(file->log->index, file->fd, F_WRLCK, - MAIL_INDEX_LOCK_SECS); + ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd, + F_WRLCK, MAIL_INDEX_LOCK_SECS); if (ret > 0) { file->locked = TRUE; return 0; @@ -162,7 +162,8 @@ return; } - ret = mail_index_lock_fd(file->log->index, file->fd, F_UNLCK, 0); + ret = mail_index_lock_fd(file->log->index, file->filepath, file->fd, + F_UNLCK, 0); if (ret <= 0) { mail_index_file_set_syscall_error(file->log->index, file->filepath,