From 84aa0c137d6c777316fed8cb198343bd8e69c04e Mon Sep 17 00:00:00 2001 From: Jason Madden Date: Mon, 4 Mar 2013 07:13:39 -0600 Subject: [PATCH] Correct potential deadlock in ClientStorage:tpc_begin by being sure to release locks in a finally block. --- src/ZEO/ClientStorage.py | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/ZEO/ClientStorage.py b/src/ZEO/ClientStorage.py index b32d52c6b..51825943b 100644 --- a/src/ZEO/ClientStorage.py +++ b/src/ZEO/ClientStorage.py @@ -1111,19 +1111,20 @@ def tpc_begin(self, txn, tid=None, status=' '): if self._is_read_only: raise POSException.ReadOnlyError() self._tpc_cond.acquire() - self._midtxn_disconnect = 0 - while self._transaction is not None: - # It is allowable for a client to call two tpc_begins in a - # row with the same transaction, and the second of these - # must be ignored. - if self._transaction == txn: - self._tpc_cond.release() - raise POSException.StorageTransactionError( - "Duplicate tpc_begin calls for same transaction") - - self._tpc_cond.wait(30) - self._transaction = txn - self._tpc_cond.release() + try: + self._midtxn_disconnect = 0 + while self._transaction is not None: + # It is allowable for a client to call two tpc_begins in a + # row with the same transaction, and the second of these + # must be ignored. + if self._transaction == txn: + raise POSException.StorageTransactionError( + "Duplicate tpc_begin calls for same transaction") + + self._tpc_cond.wait(30) + self._transaction = txn + finally: + self._tpc_cond.release() try: self._server.tpc_begin(id(txn), txn.user, txn.description, @@ -1143,9 +1144,11 @@ def end_transaction(self): # the right way to set self._transaction to None # calls notify() on _tpc_cond in case there are waiting threads self._tpc_cond.acquire() - self._transaction = None - self._tpc_cond.notify() - self._tpc_cond.release() + try: + self._transaction = None + self._tpc_cond.notify() + finally: + self._tpc_cond.release() def lastTransaction(self): return self._cache.getLastTid()