# HG changeset patch # User Timo Sirainen # Date 1233778381 18000 # Node ID 8cca2bf6ab768eaa97d5d7c048146fd1dc652bc9 # Parent 25dfff279eda0bc93e1bfb7f73257ef7493c5e52 mbox: flock() and lockf() now use blocking alarm()ed locking. diff -r 25dfff279eda -r 8cca2bf6ab76 src/lib-storage/index/mbox/mbox-lock.c --- a/src/lib-storage/index/mbox/mbox-lock.c Wed Feb 04 14:59:41 2009 -0500 +++ b/src/lib-storage/index/mbox/mbox-lock.c Wed Feb 04 15:13:01 2009 -0500 @@ -423,6 +423,7 @@ time_t max_wait_time) { time_t now, last_notify; + unsigned int next_alarm; if (mbox_file_open_latest(ctx, lock_type) < 0) return -1; @@ -437,26 +438,49 @@ else lock_type = LOCK_UN; + if (max_wait_time == 0) { + /* usually we're waiting here, but if we came from + mbox_lock_dotlock(), we just want to try locking */ + lock_type |= LOCK_NB; + } else { + now = time(NULL); + if (now >= max_wait_time) + alarm(1); + else + alarm(I_MIN(max_wait_time - now, 5)); + } + last_notify = 0; - while (flock(ctx->mbox->mbox_fd, lock_type | LOCK_NB) < 0) { - if (errno != EWOULDBLOCK) { + while (flock(ctx->mbox->mbox_fd, lock_type) < 0) { + if (errno != EINTR) { + if (errno == EWOULDBLOCK && max_wait_time == 0) { + /* non-blocking lock trying failed */ + return 0; + } + alarm(0); mbox_set_syscall_error(ctx->mbox, "flock()"); return -1; } now = time(NULL); - if (now >= max_wait_time) + if (now >= max_wait_time) { + alarm(0); return 0; - - if (now != last_notify) { - index_storage_lock_notify(&ctx->mbox->ibox, - MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT, - max_wait_time - now); } - usleep(LOCK_RANDOM_USLEEP_TIME); + /* notify locks once every 5 seconds. + try to use rounded values. */ + next_alarm = (max_wait_time - now) % 5; + if (next_alarm == 0) + next_alarm = 5; + alarm(next_alarm); + + index_storage_lock_notify(&ctx->mbox->ibox, + MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT, + max_wait_time - now); } + alarm(0); return 1; } #endif @@ -466,6 +490,7 @@ time_t max_wait_time) { time_t now, last_notify; + unsigned int next_alarm; if (mbox_file_open_latest(ctx, lock_type) < 0) return -1; @@ -473,31 +498,53 @@ if (lock_type == F_UNLCK && ctx->mbox->mbox_fd == -1) return 1; - if (lock_type != F_UNLCK) + if (lock_type == F_UNLCK) + lock_type = F_ULOCK; + else if (max_wait_time == 0) { + /* usually we're waiting here, but if we came from + mbox_lock_dotlock(), we just want to try locking */ lock_type = F_TLOCK; - else - lock_type = F_ULOCK; + } else { + now = time(NULL); + if (now >= max_wait_time) + alarm(1); + else + alarm(I_MIN(max_wait_time - now, 5)); + lock_type = F_LOCK; + } last_notify = 0; while (lockf(ctx->mbox->mbox_fd, lock_type, 0) < 0) { - if (errno != EAGAIN) { + if (errno != EINTR) { + if ((errno == EACCES || errno == EAGAIN) && + max_wait_time == 0) { + /* non-blocking lock trying failed */ + return 0; + } + alarm(0); mbox_set_syscall_error(ctx->mbox, "lockf()"); return -1; } now = time(NULL); - if (now >= max_wait_time) + if (now >= max_wait_time) { + alarm(0); return 0; - - if (now != last_notify) { - index_storage_lock_notify(&ctx->mbox->ibox, - MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT, - max_wait_time - now); } - usleep(LOCK_RANDOM_USLEEP_TIME); + /* notify locks once every 5 seconds. + try to use rounded values. */ + next_alarm = (max_wait_time - now) % 5; + if (next_alarm == 0) + next_alarm = 5; + alarm(next_alarm); + + index_storage_lock_notify(&ctx->mbox->ibox, + MAILBOX_LOCK_NOTIFY_MAILBOX_ABORT, + max_wait_time - now); } + alarm(0); return 1; } #endif