Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit32e7715

Browse files
bpo-45997: Fix asyncio.Semaphore re-acquiring order (GH-31910)
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
1 parent673755b commit32e7715

File tree

3 files changed

+36
-6
lines changed

3 files changed

+36
-6
lines changed

‎Lib/asyncio/locks.py‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from .importexceptions
88
from .importmixins
9+
from .importtasks
910

1011

1112
class_ContextManagerMixin:
@@ -346,6 +347,7 @@ def __init__(self, value=1):
346347
raiseValueError("Semaphore initial value must be >= 0")
347348
self._value=value
348349
self._waiters=collections.deque()
350+
self._wakeup_scheduled=False
349351

350352
def__repr__(self):
351353
res=super().__repr__()
@@ -359,6 +361,7 @@ def _wake_up_next(self):
359361
waiter=self._waiters.popleft()
360362
ifnotwaiter.done():
361363
waiter.set_result(None)
364+
self._wakeup_scheduled=True
362365
return
363366

364367
deflocked(self):
@@ -374,16 +377,17 @@ async def acquire(self):
374377
called release() to make it larger than 0, and then return
375378
True.
376379
"""
377-
whileself._value<=0:
380+
# _wakeup_scheduled is set if *another* task is scheduled to wakeup
381+
# but its acquire() is not resumed yet
382+
whileself._wakeup_scheduledorself._value<=0:
378383
fut=self._get_loop().create_future()
379384
self._waiters.append(fut)
380385
try:
381386
awaitfut
382-
except:
383-
# See the similar code in Queue.get.
384-
fut.cancel()
385-
ifself._value>0andnotfut.cancelled():
386-
self._wake_up_next()
387+
# reset _wakeup_scheduled *after* waiting for a future
388+
self._wakeup_scheduled=False
389+
exceptexceptions.CancelledError:
390+
self._wake_up_next()
387391
raise
388392
self._value-=1
389393
returnTrue

‎Lib/test/test_asyncio/test_locks.py‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,6 +917,31 @@ async def test_release_no_waiters(self):
917917
sem.release()
918918
self.assertFalse(sem.locked())
919919

920+
asyncdeftest_acquire_fifo_order(self):
921+
sem=asyncio.Semaphore(1)
922+
result= []
923+
924+
asyncdefcoro(tag):
925+
awaitsem.acquire()
926+
result.append(f'{tag}_1')
927+
awaitasyncio.sleep(0.01)
928+
sem.release()
929+
930+
awaitsem.acquire()
931+
result.append(f'{tag}_2')
932+
awaitasyncio.sleep(0.01)
933+
sem.release()
934+
935+
asyncwithasyncio.TaskGroup()astg:
936+
tg.create_task(coro('c1'))
937+
tg.create_task(coro('c2'))
938+
tg.create_task(coro('c3'))
939+
940+
self.assertEqual(
941+
['c1_1','c2_1','c3_1','c1_2','c2_2','c3_2'],
942+
result
943+
)
944+
920945

921946
if__name__=='__main__':
922947
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix:class:`asyncio.Semaphore` re-aquiring FIFO order.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp