Skip to content

Commit

Permalink
(fix) Edge case of acquiring lock and immediately cancelled
Browse files Browse the repository at this point in the history
  • Loading branch information
michalc committed May 2, 2019
1 parent 8e037d7 commit 6b5eaee
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
12 changes: 11 additions & 1 deletion fifolock.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from asyncio import (
CancelledError as _CancelledError,
)
from collections import (
defaultdict as _defaultdict,
deque as _deque,
Expand Down Expand Up @@ -39,7 +42,14 @@ async def __aenter__(self):
lock_mode = self._lock_mode_type()
self._waiters.append(lock_mode)
self._maybe_acquire()
await lock_mode
try:
await lock_mode
except _CancelledError:
# The waiter could have been resolved, but the task then cancelled
if lock_mode.done() and not lock_mode.cancelled():
self._holds[type(lock_mode)] -= 1
self._maybe_acquire()
raise

async def __aexit__(self, _, __, ___):
self._holds[self._lock_mode_type] -= 1
Expand Down
32 changes: 32 additions & 0 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,38 @@ async def test_mutex_cancelled_before_it_acquires_allows_later_mutex(self):
self.assertEqual(acquisition_history[1], [True, False, False])
self.assertEqual(acquisition_history[2], [True, False, True])

@async_test
async def test_mutex_cancelled_that_cancels_second_task_allows_third(self):

lock = FifoLock()
done = asyncio.Future()
acquired_1 = asyncio.Future()
acquired_3 = asyncio.Future()

async def access_1():
try:
async with lock(Mutex):
acquired_1.set_result(None)
await done
except asyncio.CancelledError:
task_2.cancel()

async def access_2():
async with lock(Mutex):
await done

async def access_3():
async with lock(Mutex):
acquired_3.set_result(None)

task_1 = asyncio.ensure_future(access_1())
task_2 = asyncio.ensure_future(access_2())
asyncio.ensure_future(access_3())

await acquired_1
task_1.cancel()
await acquired_3

@async_test
async def test_mutex_requested_concurrently_can_acquire(self):

Expand Down

0 comments on commit 6b5eaee

Please sign in to comment.