8000 gh-117657: TSAN Fix races in `PyMember_Get` and `PyMember_Set`, for C extensions by dpdani · Pull Request #123211 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-117657: TSAN Fix races in PyMember_Get and PyMember_Set, for C extensions #123211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d63eccb
gh-117657: TSAN Fix races in `PyMember_Get` and `PyMember_Set`, for C…
dpdani Aug 21, 2024
c2d3d41
exercise race in T_CHAR as well
dpdani Aug 21, 2024
f6ba4a3
signed char races
dpdani Aug 22, 2024
d9614b7
unsigned char race
dpdani Aug 22, 2024
1659849
unsigned char race 👀
dpdani Aug 22, 2024
4cfa619
unsigned char race 👀
dpdani Aug 22, 2024
107a9f5
signed short race
dpdani Aug 22, 2024
e20b9d1
unsigned short race
dpdani Aug 22, 2024
86a0945
signed int race
dpdani Aug 22, 2024
1a07031
who uses MSC anyways?
dpdani Aug 22, 2024
16f61d8
unsigned int races
dpdani Aug 22, 2024
cf25726
👀
dpdani Aug 22, 2024
d41132c
signed long race
dpdani Aug 22, 2024
2212605
unsigned long race
dpdani Aug 22, 2024
74616d6
ssizet race
dpdani Aug 22, 2024
23d10c6
float race
dpdani Aug 22, 2024
ae37a8e
double race
8000 dpdani Aug 22, 2024
bce02d0
T_CHAR
dpdani Aug 22, 2024
afe2504
signed long long race
dpdani Aug 22, 2024
3dfaab8
unsigned long long race
dpdani Aug 22, 2024
50a7bb6
fix return type
dpdani Aug 22, 2024
416e0bb
arm64 does not have 128-bit integers, I suppose
dpdani Aug 22, 2024
4bd6927
at this point I'm just making guesses
dpdani Aug 22, 2024
a4c094b
scope
dpdani Aug 29, 2024
267f995
must 0-initialize
dpdani Aug 29, 2024
c006e1d
FT_ATOMIC_STORE_CHAR_RELEASE -> FT_ATOMIC_STORE_CHAR_RELAXED
dpdani Aug 29, 2024
488dea5
remaining release -> relaxed
dpdani Aug 29, 2024
b3b07d5
default build
dpdani Aug 29, 2024
761257e
Apply suggestions from code review
dpdani Sep 22, 2024
d045747
missing load
dpdani Sep 22, 2024
c1b4c35
fixes
dpdani Nov 2, 2024
6c5cec5
Merge branch 'main' into gh-117657-tsan-pymember-c-ext
colesbury Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
gh-117657: TSAN Fix races in PyMember_Get and PyMember_Set, for C…
… extensions
  • Loading branch information
dpdani committed Aug 21, 2024
commit d63eccb09d7b2b1e0538b1d4aff3d9cadb5df648
1 change: 1 addition & 0 deletions Lib/test/libregrtest/tsan.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
'test_threading_local',
'test_threadsignals',
'test_weakref',
'test_free_threading.test_slots',
]


Expand Down
228 changes: 228 additions & 0 deletions Lib/test/test_free_threading/test_slots.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import _testcapi
import threading
from test.support import threading_helper
from unittest import TestCase
Expand Down Expand Up @@ -41,3 +42,230 @@ def reader():
assert 0 <= eggs <= iters

run_in_threads([writer, reader, reader, reader])

def test_T_BOOL(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
# different code paths for True and False
spam_old.T_BOOL = True
spam_new.T_BOOL = True
spam_old.T_BOOL = False
spam_new.T_BOOL = False

def reader():
for _ in range(1_000):
spam_old.T_BOOL
spam_new.T_BOOL

run_in_threads([writer, reader])

def test_T_BYTE(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_BYTE = 0
spam_new.T_BYTE = 0

def reader():
for _ in range(1_000):
spam_old.T_BYTE
spam_new.T_BYTE

run_in_threads([writer, reader])

def test_T_UBYTE(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_UBYTE = 0
spam_new.T_UBYTE = 0

def reader():
for _ in range(1_000):
spam_old.T_UBYTE
spam_new.T_UBYTE

run_in_threads([writer, reader])

def test_T_SHORT(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_SHORT = 0
spam_new.T_SHORT = 0

def reader():
for _ in range(1_000):
spam_old.T_SHORT
spam_new.T_SHORT

run_in_threads([writer, reader])

def test_T_USHORT(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_USHORT = 0
spam_new.T_USHORT = 0

def reader():
for _ in range(1_000):
spam_old.T_USHORT
spam_new.T_USHORT

run_in_threads([writer, reader])

def test_T_INT(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_INT = 0
spam_new.T_INT = 0

def reader():
for _ in range(1_000):
spam_old.T_INT
spam_new.T_INT

run_in_threads([writer, reader])

def test_T_UINT(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_UINT = 0
spam_new.T_UINT = 0

def reader():
for _ in range(1_000):
spam_old.T_UINT
spam_new.T_UINT

run_in_threads([writer, reader])

def test_T_LONG(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_LONG = 0
spam_new.T_LONG = 0

def reader():
for _ in range(1_000):
spam_old.T_LONG
spam_new.T_LONG

run_in_threads([writer, reader])

def test_T_ULONG(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_ULONG = 0
spam_new.T_ULONG = 0

def reader():
for _ in range(1_000):
spam_old.T_ULONG
spam_new.T_ULONG

run_in_threads([writer, reader])

def test_T_PYSSIZET(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_PYSSIZET = 0
spam_new.T_PYSSIZET = 0

def reader():
for _ in range(1_000):
spam_old.T_PYSSIZET
spam_new.T_PYSSIZET

run_in_threads([writer, reader])

def test_T_FLOAT(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_FLOAT = 0.0
spam_new.T_FLOAT = 0.0

def reader():
for _ in range(1_000):
spam_old.T_FLOAT
spam_new.T_FLOAT

run_in_threads([writer, reader])

def test_T_DOUBLE(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_DOUBLE = 0.0
spam_new.T_DOUBLE = 0.0

def reader():
for _ in range(1_000):
spam_old.T_DOUBLE
spam_new.T_DOUBLE

run_in_threads([writer, reader])

def test_T_LONGLONG(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_LONGLONG = 0
spam_new.T_LONGLONG = 0

def reader():
for _ in range(1_000):
spam_old.T_LONGLONG
spam_new.T_LONGLONG

run_in_threads([writer, reader])

def test_T_ULONGLONG(self):
spam_old = _testcapi._test_structmembersType_OldAPI()
spam_new = _testcapi._test_structmembersType_NewAPI()

def writer():
for _ in range(1_000):
spam_old.T_ULONGLONG = 0
spam_new.T_ULONGLONG = 0

def reader():
for _ in range(1_000):
spam_old.T_ULONGLONG
spam_new.T_ULONGLONG

run_in_threads([writer, reader])
0