Skip to content

gh-151364: Fix data race on kqueue file descriptor in free-threaded build - #158647

Open
AHAariyan wants to merge 1 commit into
python:mainfrom
AHAariyan:gh-151364-kqueue-race
Open

AHAariyan wants to merge 1 commit into
python:mainfrom
AHAariyan:gh-151364-kqueue-race

Conversation

@AHAariyan

@AHAariyan AHAariyan commented Oct 3, 2026 •

Copy link
Copy Markdown

Continues @vstinner's closed GH-151376 (as he suggested on that PR).

select.kqueue.close() writes kqfd while holding the object's critical section, but the closed getter, fileno() and control() read it without synchronization, so TSan reports data races on the free-threaded build.

This PR uses relaxed atomic loads/stores for kqfd instead of critical sections, following @ZeroIntensity's suggestion on GH-151376:

  • close() stores -1 with FT_ATOMIC_STORE_INT_RELAXED.
  • closed, fileno() and control() read it with FT_ATOMIC_LOAD_INT_RELAXED. fileno() now reads the field once, so it can't pass the check and then return -1.
  • The read in control() that is passed to kevent() happens inside Py_BEGIN_ALLOW_THREADS, where a critical section would not protect it; an atomic load does.
  • No locking added to __init__ or tp_finalize, per the review on gh-151364: Add critical sections to kqueue #151376.
  • The GIL build is unchanged (the macros compile to plain accesses).

The kevent repr/richcompare changes from GH-151376 are left for a separate PR.

Test: added Lib/test/test_free_threading/test_select.py (skipped where kqueue is unavailable): one thread closes a kqueue while others read closed and call fileno()/control().

Verified on macOS arm64, free-threaded debug build with --with-thread-sanitizer:

  • unpatched main (a4f28a5): the new test triggers 3–5 TSan data-race reports per run
  • patched: 0 reports in 15/15 runs
  • test_kqueue, test_select, test_selectors, test_free_threading pass; -R 3:3 refleak check clean; make patchcheck clean

@python-cla-bot

python-cla-bot Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant