Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions Lib/test/test_free_threading/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@


class SysModuleTest(unittest.TestCase):
@unittest.skipUnless(hasattr(sys, "setdlopenflags"),
"test needs sys.setdlopenflags()")
def test_dlopenflags_concurrent(self):
# gh-151644: getdlopenflags() and setdlopenflags() must be safe to
# call concurrently in free-threaded builds.
original = sys.getdlopenflags()
self.addCleanup(sys.setdlopenflags, original)

# Use a small set of known-valid flag values to avoid integer overflow.
flag_values = [1, 2, 256, 257]

def worker(worker_id):
for i in range(20_000):
if worker_id % 2 == 0:
sys.getdlopenflags()
else:
sys.setdlopenflags(flag_values[worker_id % len(flag_values)])

workers = [lambda i=i: worker(i) for i in range(6)]
threading_helper.run_concurrently(workers)

def test_int_max_str_digits_thread(self):
# gh-151218: Check that it's safe to call get_int_max_str_digits() and
# set_int_max_str_digits() in parallel. Previously, this test triggered
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fix a data race in :func:`sys.setdlopenflags` and :func:`sys.getdlopenflags`
when called concurrently in the free-threaded build. The underlying
``_PyImport_GetDLOpenFlags`` and ``_PyImport_SetDLOpenFlags`` functions now
use atomic load/store operations.
4 changes: 2 additions & 2 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,13 +908,13 @@ _PyImport_SwapPackageContext(const char *newcontext)
int
_PyImport_GetDLOpenFlags(PyInterpreterState *interp)
{
return DLOPENFLAGS(interp);
return FT_ATOMIC_LOAD_INT_RELAXED(DLOPENFLAGS(interp));
}

void
_PyImport_SetDLOpenFlags(PyInterpreterState *interp, int new_val)
{
DLOPENFLAGS(interp) = new_val;
FT_ATOMIC_STORE_INT_RELAXED(DLOPENFLAGS(interp), new_val);
}
#endif // HAVE_DLOPEN

Expand Down
Loading