From: Ronnie Sahlberg Date: Wed, 14 May 2014 22:13:21 GMT Subject: [PATCH 22/31] refs.c: release all remaining locks during transaction_free Message-ID: <1400105610-21194-23-git-send-email-sahlberg@google.com> In-Reply-To: <1400105610-21194-1-git-send-email-sahlberg@google.com> If there are remaining locks held when we free a transaction, make sure that we release them instead of relying on the atexit magic to release them for us. Otherwise, if we perform two transactions on the same ref and the first transaction is aborted then the second transaction will fail to lock the ref. This can currently not trigger since there are no commands that use multiple transactions. This sequence illustrates the bug: t = transaction_begin() /* first transaction */ transaction_update_sha1(t, ref, ...) /* ref is locked */ transaction_free(t) t = transaction_begin() /* second transaction */ transaction_update_sha1(t, ref, ...) /* will fail since ref was locked above */ Signed-off-by: Ronnie Sahlberg --- refs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/refs.c b/refs.c index 87cdd91..17feec5 100644 --- a/refs.c +++ b/refs.c @@ -3325,6 +3325,8 @@ void transaction_free(struct ref_transaction *transaction) return; for (i = 0; i < transaction->nr; i++) { + if (transaction->updates[i]->lock) + unlock_ref(transaction->updates[i]->lock); free((char *)transaction->updates[i]->committer); free((char *)transaction->updates[i]->msg); free(transaction->updates[i]); @@ -3729,8 +3731,10 @@ cleanup: : REF_TRANSACTION_CLOSED; for (i = 0; i < n; i++) - if (updates[i]->lock) + if (updates[i]->lock) { unlock_ref(updates[i]->lock); + updates[i]->lock = NULL; + } return ret; } -- 2.0.0.rc3.506.g3739a35