Skip to content

Commit

Permalink
pythongh-117657: TSAN Fix races in PyMember_Get and PyMember_Set,…
Browse files Browse the repository at this point in the history
… for C extensions
  • Loading branch information
dpdani committed Aug 21, 2024
1 parent b1d3bd2 commit d63eccb
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 0 deletions.
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 comments on commit d63eccb

Please sign in to comment.