From: Timo Sirainen Date: Sun, 22 Sep 2013 03:30:47 +0000 (+0300) Subject: mbox: Fixed assert-crash due to wrong transaction_count handling. X-Git-Tag: 2.2.6~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=fb100955a1215b4ce3ac89171fcd95c211169f46;p=thirdparty%2Fdovecot%2Fcore.git mbox: Fixed assert-crash due to wrong transaction_count handling. This happened only when messages had been expunged by another session just before saving a new message. --- diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index 0d4195182f..4b6fef54a9 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -737,7 +737,8 @@ mbox_transaction_unlock(struct mailbox *box, unsigned int lock_id1, if (lock_id2 != 0) mbox_unlock(mbox, lock_id2); if (mbox->mbox_global_lock_id == 0) { - i_assert(mbox->box.transaction_count > 0 || + i_assert(mbox->box.transaction_count > 0); + i_assert(mbox->box.transaction_count > 1 || mbox->external_transactions > 0 || mbox->mbox_lock_type == F_UNLCK); } else { diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index 415b00c6f3..4e753f45c3 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -1836,15 +1836,15 @@ int mailbox_transaction_commit_get_changes( struct mail_transaction_commit_changes *changes_r) { struct mailbox_transaction_context *t = *_t; + struct mailbox *box = t->box; unsigned int save_count = t->save_count; int ret; - t->box->transaction_count--; changes_r->pool = NULL; *_t = NULL; T_BEGIN { - ret = t->box->v.transaction_commit(t, changes_r); + ret = box->v.transaction_commit(t, changes_r); } T_END; /* either all the saved messages get UIDs or none, because a) we failed, b) MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS not set, @@ -1852,6 +1852,11 @@ int mailbox_transaction_commit_get_changes( i_assert(ret < 0 || seq_range_count(&changes_r->saved_uids) == save_count || array_count(&changes_r->saved_uids) == 0); + /* decrease the transaction count only after transaction_commit(). + that way if it creates and destroys transactions internally, we + don't see transaction_count=0 until the parent transaction is fully + finished */ + box->transaction_count--; if (ret < 0 && changes_r->pool != NULL) pool_unref(&changes_r->pool); return ret; @@ -1860,11 +1865,11 @@ int mailbox_transaction_commit_get_changes( void mailbox_transaction_rollback(struct mailbox_transaction_context **_t) { struct mailbox_transaction_context *t = *_t; - - t->box->transaction_count--; + struct mailbox *box = t->box; *_t = NULL; - t->box->v.transaction_rollback(t); + box->v.transaction_rollback(t); + box->transaction_count--; } unsigned int mailbox_transaction_get_count(const struct mailbox *box)