Skip to content

Commit

Permalink
Correct potential deadlock in ClientStorage:tpc_begin by being sure t…
Browse files Browse the repository at this point in the history
…o release locks in a finally block.
  • Loading branch information
jamadden committed Mar 4, 2013
1 parent 09db1b2 commit 84aa0c1
Showing 1 changed file with 19 additions and 16 deletions.
35 changes: 19 additions & 16 deletions src/ZEO/ClientStorage.py
Expand Up @@ -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,
Expand All @@ -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()
Expand Down

0 comments on commit 84aa0c1

Please sign in to comment.