Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
2f79c014
Kaydet (Commit)
2f79c014
authored
Şub 02, 2018
tarafından
Bar Harel
Kaydeden (comit)
Yury Selivanov
Şub 02, 2018
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
bpo-32734: Fix asyncio.Lock multiple acquire safety issue (GH-5466)
üst
66771422
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
75 additions
and
10 deletions
+75
-10
locks.py
Lib/asyncio/locks.py
+22
-10
test_locks.py
Lib/test/test_asyncio/test_locks.py
+50
-0
ACKS
Misc/ACKS
+1
-0
2018-02-01-01-34-47.bpo-32734.gCV9AD.rst
...S.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst
+2
-0
No files found.
Lib/asyncio/locks.py
Dosyayı görüntüle @
2f79c014
...
...
@@ -183,16 +183,22 @@ class Lock(_ContextManagerMixin):
fut
=
self
.
_loop
.
create_future
()
self
.
_waiters
.
append
(
fut
)
# Finally block should be called before the CancelledError
# handling as we don't want CancelledError to call
# _wake_up_first() and attempt to wake up itself.
try
:
await
fut
self
.
_locked
=
True
return
True
try
:
await
fut
finally
:
self
.
_waiters
.
remove
(
fut
)
except
futures
.
CancelledError
:
if
not
self
.
_locked
:
self
.
_wake_up_first
()
raise
finally
:
self
.
_waiters
.
remove
(
fut
)
self
.
_locked
=
True
return
True
def
release
(
self
):
"""Release a lock.
...
...
@@ -212,11 +218,17 @@ class Lock(_ContextManagerMixin):
raise
RuntimeError
(
'Lock is not acquired.'
)
def
_wake_up_first
(
self
):
"""Wake up the first waiter who isn't cancelled."""
for
fut
in
self
.
_waiters
:
if
not
fut
.
done
():
fut
.
set_result
(
True
)
break
"""Wake up the first waiter if it isn't done."""
try
:
fut
=
next
(
iter
(
self
.
_waiters
))
except
StopIteration
:
return
# .done() necessarily means that a waiter will wake up later on and
# either take the lock, or, if it was cancelled and lock wasn't
# taken already, will hit this again and wake up a new waiter.
if
not
fut
.
done
():
fut
.
set_result
(
True
)
class
Event
:
...
...
Lib/test/test_asyncio/test_locks.py
Dosyayı görüntüle @
2f79c014
...
...
@@ -200,6 +200,56 @@ class LockTests(test_utils.TestCase):
self
.
assertTrue
(
tb
.
cancelled
())
self
.
assertTrue
(
tc
.
done
())
def
test_cancel_release_race
(
self
):
# Issue 32734
# Acquire 4 locks, cancel second, release first
# and 2 locks are taken at once.
lock
=
asyncio
.
Lock
(
loop
=
self
.
loop
)
lock_count
=
0
call_count
=
0
async
def
lockit
():
nonlocal
lock_count
nonlocal
call_count
call_count
+=
1
await
lock
.
acquire
()
lock_count
+=
1
async
def
lockandtrigger
():
await
lock
.
acquire
()
self
.
loop
.
call_soon
(
trigger
)
def
trigger
():
t1
.
cancel
()
lock
.
release
()
t0
=
self
.
loop
.
create_task
(
lockandtrigger
())
t1
=
self
.
loop
.
create_task
(
lockit
())
t2
=
self
.
loop
.
create_task
(
lockit
())
t3
=
self
.
loop
.
create_task
(
lockit
())
# First loop acquires all
test_utils
.
run_briefly
(
self
.
loop
)
self
.
assertTrue
(
t0
.
done
())
# Second loop calls trigger
test_utils
.
run_briefly
(
self
.
loop
)
# Third loop calls cancellation
test_utils
.
run_briefly
(
self
.
loop
)
# Make sure only one lock was taken
self
.
assertEqual
(
lock_count
,
1
)
# While 3 calls were made to lockit()
self
.
assertEqual
(
call_count
,
3
)
self
.
assertTrue
(
t1
.
cancelled
()
and
t2
.
done
())
# Cleanup the task that is stuck on acquire.
t3
.
cancel
()
test_utils
.
run_briefly
(
self
.
loop
)
self
.
assertTrue
(
t3
.
cancelled
())
def
test_finished_waiter_cancelled
(
self
):
lock
=
asyncio
.
Lock
(
loop
=
self
.
loop
)
...
...
Misc/ACKS
Dosyayı görüntüle @
2f79c014
...
...
@@ -602,6 +602,7 @@ Milton L. Hankins
Stephen Hansen
Barry Hantman
Lynda Hardman
Bar Harel
Derek Harland
Jason Harper
David Harrigan
...
...
Misc/NEWS.d/next/Library/2018-02-01-01-34-47.bpo-32734.gCV9AD.rst
0 → 100644
Dosyayı görüntüle @
2f79c014
Fixed ``asyncio.Lock()`` safety issue which allowed acquiring and locking
the same lock multiple times, without it being free. Patch by Bar Harel.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment