Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit 8ff596c4 authored by David Faure's avatar David Faure

Akonadi: fix dangling transaction after itemsync failure

Summary:
TransactionSequence was emitting result() twice when rolling back.

* How did this happen?
The TransactionRollbackJob is (automatically) added as a subjob of the
TransactionSequence, so when it finishes, slotResult is called (like for
all subjobs), as well as rollbackResult().
Since the latter emits result() already [mostly for symmetry with
commitResult()], we don't need to do that in slotResult (which doesn't do
it for the case of committing, either).

* Why is it a problem to emit result() twice?
Well, first, it's against the law in KJob world. In practice,
ItemSyncPrivate::slotTransactionResult was called twice (for the same
TransactionSequence job) which made it decrement mTransactionJobs one
time too many.
As a result, checkDone() finished too early and didn't go into the
"commit transaction" branch for other transactions.
Leaving a transaction "open" is a good recipe for database deadlocks further
down the line.

* Why did the TransactionSequence roll back in the first place?
In my case because of the infamous and not-yet fixed "Multiple merge
candidates" problem, but it seems that it can also happen when having
items without a part, according to Volker's investigations.
All of these issues still need to be fixed, but at least akonadi seems
to be still usable after they happen.

CCBUG: 399167

Test Plan: Ctrl+L in kmail, with a folder having multiple items for the same RID

Reviewers: dvratil, vkrause

Reviewed By: dvratil

Subscribers: kfunk, kde-pim

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D19487

(cherry picked from commit f1281cf1)
parent a5805b38
......@@ -133,8 +133,6 @@ void TransactionSequence::slotResult(KJob *job)
d->mState = TransactionSequencePrivate::Committing;
TransactionCommitJob *job = new TransactionCommitJob(this);
connect(job, &TransactionCommitJob::result, [d](KJob *job) { d->commitResult(job);});
} else if (d->mState == TransactionSequencePrivate::RollingBack) {
emitResult();
}
}
} else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment