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,