forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pythongh-118362: Fix thread safety around lookups from the type cache…
… in the face of concurrent mutators (python#118454) Add _PyType_LookupRef and use incref before setting attribute on type Makes setting an attribute on a class and signaling type modified atomic Avoid adding re-entrancy exposing the type cache in an inconsistent state by decrefing after type is updated
- Loading branch information
Showing
18 changed files
with
437 additions
and
124 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
import unittest | ||
|
||
from threading import Thread | ||
from multiprocessing.dummy import Pool | ||
from unittest import TestCase | ||
|
||
from test.support import is_wasi | ||
|
||
|
||
NTHREADS = 6 | ||
BOTTOM = 0 | ||
TOP = 1000 | ||
ITERS = 100 | ||
|
||
class A: | ||
attr = 1 | ||
|
||
@unittest.skipIf(is_wasi, "WASI has no threads.") | ||
class TestType(TestCase): | ||
def test_attr_cache(self): | ||
def read(id0): | ||
for _ in range(ITERS): | ||
for _ in range(BOTTOM, TOP): | ||
A.attr | ||
|
||
def write(id0): | ||
for _ in range(ITERS): | ||
for _ in range(BOTTOM, TOP): | ||
# Make _PyType_Lookup cache hot first | ||
A.attr | ||
A.attr | ||
x = A.attr | ||
x += 1 | ||
A.attr = x | ||
|
||
|
||
with Pool(NTHREADS) as pool: | ||
pool.apply_async(read, (1,)) | ||
pool.apply_async(write, (1,)) | ||
pool.close() | ||
pool.join() | ||
|
||
def test_attr_cache_consistency(self): | ||
class C: | ||
x = 0 | ||
|
||
DONE = False | ||
def writer_func(): | ||
for i in range(3000): | ||
C.x | ||
C.x | ||
C.x += 1 | ||
nonlocal DONE | ||
DONE = True | ||
|
||
def reader_func(): | ||
while True: | ||
# We should always see a greater value read from the type than the | ||
# dictionary | ||
a = C.__dict__['x'] | ||
b = C.x | ||
self.assertGreaterEqual(b, a) | ||
|
||
if DONE: | ||
break | ||
|
||
self.run_one(writer_func, reader_func) | ||
|
||
def test_attr_cache_consistency_subclass(self): | ||
class C: | ||
x = 0 | ||
|
||
class D(C): | ||
pass | ||
|
||
DONE = False | ||
def writer_func(): | ||
for i in range(3000): | ||
D.x | ||
D.x | ||
C.x += 1 | ||
nonlocal DONE | ||
DONE = True | ||
|
||
def reader_func(): | ||
while True: | ||
# We should always see a greater value read from the type than the | ||
# dictionary | ||
a = C.__dict__['x'] | ||
b = D.x | ||
self.assertGreaterEqual(b, a) | ||
|
||
if DONE: | ||
break | ||
|
||
self.run_one(writer_func, reader_func) | ||
|
||
def run_one(self, writer_func, reader_func): | ||
writer = Thread(target=writer_func) | ||
readers = [] | ||
for x in range(30): | ||
reader = Thread(target=reader_func) | ||
readers.append(reader) | ||
reader.start() | ||
|
||
writer.start() | ||
writer.join() | ||
for reader in readers: | ||
reader.join() | ||
|
||
if __name__ == "__main__": | ||
unittest.main() |
2 changes: 2 additions & 0 deletions
2
Misc/NEWS.d/next/Core and Builtins/2024-05-01-14-20-28.gh-issue-118492.VUsSfn.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Fix an issue where the type cache can expose a previously accessed attribute | ||
when a finalizer is run. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.