dovecot-2.2: lib: Added file_wait_lock_error() and file_try_lock...
dovecot at dovecot.org
dovecot at dovecot.org
Thu Sep 25 10:29:03 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/87f10e2fac95
changeset: 17835:87f10e2fac95
user: Timo Sirainen <tss at iki.fi>
date: Thu Sep 25 13:26:20 2014 +0300
description:
lib: Added file_wait_lock_error() and file_try_lock_error()
diffstat:
src/lib/file-lock.c | 84 +++++++++++++++++++++++++++++++++++++++-------------
src/lib/file-lock.h | 11 ++++++
2 files changed, 74 insertions(+), 21 deletions(-)
diffs (193 lines):
diff -r 65963be31ceb -r 87f10e2fac95 src/lib/file-lock.c
--- a/src/lib/file-lock.c Thu Sep 25 02:55:34 2014 +0300
+++ b/src/lib/file-lock.c Thu Sep 25 13:26:20 2014 +0300
@@ -48,10 +48,19 @@
return file_wait_lock(fd, path, lock_type, lock_method, 0, lock_r);
}
+int file_try_lock_error(int fd, const char *path, int lock_type,
+ enum file_lock_method lock_method,
+ struct file_lock **lock_r, const char **error_r)
+{
+ return file_wait_lock_error(fd, path, lock_type, lock_method, 0,
+ lock_r, error_r);
+}
+
static int file_lock_do(int fd, const char *path, int lock_type,
enum file_lock_method lock_method,
- unsigned int timeout_secs)
+ unsigned int timeout_secs, const char **error_r)
{
+ const char *lock_type_str;
int ret;
i_assert(fd != -1);
@@ -59,13 +68,17 @@
if (timeout_secs != 0)
alarm(timeout_secs);
+ lock_type_str = lock_type == F_UNLCK ? "unlock" :
+ (lock_type == F_RDLCK ? "read-lock" : "write-lock");
+
switch (lock_method) {
case FILE_LOCK_METHOD_FCNTL: {
#ifndef HAVE_FCNTL
- i_fatal("fcntl() locks not supported");
+ *error_r = t_strdup_printf(
+ "Can't lock file %s: fcntl() locks not supported", path);
+ return -1;
#else
struct flock fl;
- const char *errstr;
fl.l_type = lock_type;
fl.l_whence = SEEK_SET;
@@ -81,6 +94,9 @@
if (timeout_secs == 0 &&
(errno == EACCES || errno == EAGAIN)) {
/* locked by another process */
+ *error_r = t_strdup_printf(
+ "fcntl(%s, %s, F_SETLK) locking failed: %m "
+ "(File is already locked)", path, lock_type_str);
return 0;
}
@@ -89,20 +105,22 @@
even if not, we probably want to be killed
so stop blocking. */
errno = EAGAIN;
+ *error_r = t_strdup_printf(
+ "fcntl(%s, %s, F_SETLKW) locking failed: "
+ "Timed out after %u seconds",
+ path, lock_type_str, timeout_secs);
return 0;
}
- errstr = errno != EACCES ? strerror(errno) :
- "File is locked by another process (EACCES)";
- i_error("fcntl(%s) locking failed for file %s: %s",
- lock_type == F_UNLCK ? "unlock" :
- lock_type == F_RDLCK ? "read-lock" : "write-lock",
- path, errstr);
+ *error_r = t_strdup_printf("fcntl(%s, %s, %s) locking failed: %m",
+ path, lock_type_str, timeout_secs == 0 ? "F_SETLK" : "F_SETLKW");
return -1;
#endif
}
case FILE_LOCK_METHOD_FLOCK: {
#ifndef HAVE_FLOCK
- i_fatal("flock() locks not supported");
+ *error_r = t_strdup_printf(
+ "Can't lock file %s: flock() not supported", path);
+ return -1;
#else
int operation = timeout_secs != 0 ? 0 : LOCK_NB;
@@ -124,16 +142,22 @@
if (ret == 0)
break;
- if (errno == EWOULDBLOCK || errno == EINTR) {
- /* a) locked by another process,
- b) timeouted */
- errno = EAGAIN;
+ if (timeout_secs == 0 && errno == EWOULDBLOCK) {
+ /* locked by another process */
+ *error_r = t_strdup_printf(
+ "flock(%s, %s) failed: %m "
+ "(File is already locked)", path, lock_type_str);
return 0;
}
- i_error("flock(%s) locking failed for file %s: %m",
- lock_type == F_UNLCK ? "unlock" :
- lock_type == F_RDLCK ? "read-lock" : "write-lock",
- path);
+ if (errno == EINTR) {
+ errno = EAGAIN;
+ *error_r = t_strdup_printf("flock(%s, %s) failed: "
+ "Timed out after %u seconds",
+ path, lock_type_str, timeout_secs);
+ return 0;
+ }
+ *error_r = t_strdup_printf("flock(%s, %s) failed: %m",
+ path, lock_type_str);
return -1;
#endif
}
@@ -150,10 +174,25 @@
unsigned int timeout_secs,
struct file_lock **lock_r)
{
+ const char *error;
+ int ret;
+
+ ret = file_wait_lock_error(fd, path, lock_type, lock_method,
+ timeout_secs, lock_r, &error);
+ if (ret < 0)
+ i_error("%s", error);
+ return ret;
+}
+
+int file_wait_lock_error(int fd, const char *path, int lock_type,
+ enum file_lock_method lock_method,
+ unsigned int timeout_secs,
+ struct file_lock **lock_r, const char **error_r)
+{
struct file_lock *lock;
int ret;
- ret = file_lock_do(fd, path, lock_type, lock_method, timeout_secs);
+ ret = file_lock_do(fd, path, lock_type, lock_method, timeout_secs, error_r);
if (ret <= 0)
return ret;
@@ -168,18 +207,21 @@
int file_lock_try_update(struct file_lock *lock, int lock_type)
{
+ const char *error;
+
return file_lock_do(lock->fd, lock->path, lock_type,
- lock->lock_method, 0);
+ lock->lock_method, 0, &error);
}
void file_unlock(struct file_lock **_lock)
{
struct file_lock *lock = *_lock;
+ const char *error;
*_lock = NULL;
if (file_lock_do(lock->fd, lock->path, F_UNLCK,
- lock->lock_method, 0) == 0) {
+ lock->lock_method, 0, &error) == 0) {
/* this shouldn't happen */
i_error("file_unlock(%s) failed: %m", lock->path);
}
diff -r 65963be31ceb -r 87f10e2fac95 src/lib/file-lock.h
--- a/src/lib/file-lock.h Thu Sep 25 02:55:34 2014 +0300
+++ b/src/lib/file-lock.h Thu Sep 25 13:26:20 2014 +0300
@@ -25,12 +25,23 @@
int file_try_lock(int fd, const char *path, int lock_type,
enum file_lock_method lock_method,
struct file_lock **lock_r);
+/* Like file_try_lock(), but return the error message as a string instead
+ of logging it. Also when returning 0 an error message is returned. */
+int file_try_lock_error(int fd, const char *path, int lock_type,
+ enum file_lock_method lock_method,
+ struct file_lock **lock_r, const char **error_r);
/* Like lock_try_lock(), but return 0 only after having tried to lock for
timeout_secs. */
int file_wait_lock(int fd, const char *path, int lock_type,
enum file_lock_method lock_method,
unsigned int timeout_secs,
struct file_lock **lock_r);
+/* Like file_wait_lock(), but return the error message as a string instead
+ of logging it. Also when returning 0 an error message is returned. */
+int file_wait_lock_error(int fd, const char *path, int lock_type,
+ enum file_lock_method lock_method,
+ unsigned int timeout_secs,
+ struct file_lock **lock_r, const char **error_r);
/* Change the lock type. */
int file_lock_try_update(struct file_lock *lock, int lock_type);
More information about the dovecot-cvs
mailing list