MAIL_DUPLICATE_LOCK_IO_ERROR,
MAIL_DUPLICATE_LOCK_TIMEOUT,
MAIL_DUPLICATE_LOCK_TOO_MANY,
+ MAIL_DUPLICATE_LOCK_DEADLOCK,
};
struct mail_duplicate_lock {
i_assert(lock->fd == -1);
i_assert(lock->lock == NULL);
- if (errno != EAGAIN) {
+ if (errno == EDEADLK) {
+ /* deadlock */
+ result = MAIL_DUPLICATE_LOCK_DEADLOCK;
+ } else if (errno != EAGAIN) {
/* not a lock timeout */
result = MAIL_DUPLICATE_LOCK_IO_ERROR;
} else {
e_debug(trans->event,
"Check ID: too many IDs locked");
return MAIL_DUPLICATE_CHECK_RESULT_TOO_MANY_LOCKS;
+ case MAIL_DUPLICATE_LOCK_DEADLOCK:
+ e_debug(trans->event,
+ "Check ID: deadlock detected while locking");
+ return MAIL_DUPLICATE_CHECK_RESULT_DEADLOCK;
}
mail_duplicate_update(trans);
MAIL_DUPLICATE_CHECK_RESULT_LOCK_TIMEOUT,
/* Too many locks held. */
MAIL_DUPLICATE_CHECK_RESULT_TOO_MANY_LOCKS,
+ /* Locking detected a deadlock. The caller should rollback the
+ transaction to release all locks, do a short random sleep, retry
+ and hope that the next attempt succeeds. */
+ MAIL_DUPLICATE_CHECK_RESULT_DEADLOCK,
};
#define MAIL_DUPLICATE_DEFAULT_KEEP (3600 * 24)