cpython/Misc
mpage 33da0e844c
gh-114271: Fix race in Thread.join() (#114839)
There is a race between when `Thread._tstate_lock` is released[^1] in `Thread._wait_for_tstate_lock()`
and when `Thread._stop()` asserts[^2] that it is unlocked. Consider the following execution
involving threads A, B, and C:

1. A starts.
2. B joins A, blocking on its `_tstate_lock`.
3. C joins A, blocking on its `_tstate_lock`.
4. A finishes and releases its `_tstate_lock`.
5. B acquires A's `_tstate_lock` in `_wait_for_tstate_lock()`, releases it, but is swapped
   out before calling `_stop()`.
6. C is scheduled, acquires A's `_tstate_lock` in `_wait_for_tstate_lock()` but is swapped
   out before releasing it.
7. B is scheduled, calls `_stop()`, which asserts that A's `_tstate_lock` is not held.
   However, C holds it, so the assertion fails.

The race can be reproduced[^3] by inserting sleeps at the appropriate points in
the threading code. To do so, run the `repro_join_race.py` from the linked repo.

There are two main parts to this PR:

1. `_tstate_lock` is replaced with an event that is attached to `PyThreadState`.
   The event is set by the runtime prior to the thread being cleared (in the same
   place that `_tstate_lock` was released). `Thread.join()` blocks waiting for the
   event to be set.
2. `_PyInterpreterState_WaitForThreads()` provides the ability to wait for all
   non-daemon threads to exit. To do so, an `is_daemon` predicate was added to
   `PyThreadState`. This field is set each time a thread is created. `threading._shutdown()`
   now calls into `_PyInterpreterState_WaitForThreads()` instead of waiting on
   `_tstate_lock`s.

[^1]: 441affc9e7/Lib/threading.py (L1201)
[^2]: 441affc9e7/Lib/threading.py (L1115)
[^3]: 8194653279

---------

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Antoine Pitrou <antoine@python.org>
2024-03-16 13:56:30 +01:00
..
NEWS.d gh-114271: Fix race in Thread.join() (#114839) 2024-03-16 13:56:30 +01:00
rhel7
ACKS gh-89547: Support for nesting special forms like Final (#116096) 2024-03-11 23:11:56 -07:00
coverity_model.c
externals.spdx.json gh-112844: Add SBOM for external dependencies (#115789) 2024-02-29 17:38:04 +02:00
HISTORY Fix a misspelling of Interpeter -> Interpreter (GH-111040) 2023-10-18 15:09:45 -07:00
indent.pro
platform_triplet.c gh-71052: Change Android's sys.platform from "linux" to "android" 2024-03-11 19:25:39 +00:00
Porting
python-config.in bpo-45101: Add consistency in usage message IO between 2 versions of python-config (GH-28162) 2024-02-26 22:04:44 +02:00
python-config.sh.in bpo-45101: Add consistency in usage message IO between 2 versions of python-config (GH-28162) 2024-02-26 22:04:44 +02:00
python-embed.pc.in
python.man gh-116167: Allow disabling the GIL with PYTHON_GIL=0 or -X gil=0 (#116338) 2024-03-11 11:02:58 -04:00
python.pc.in
README
README.AIX
README.coverity
README.valgrind
sbom.spdx.json gh-116116: Backport blake2 change to fix building with clang-cl on windows-i686 (GH-116117) 2024-03-04 16:59:57 +00:00
SpecialBuilds.txt
stable_abi.toml gh-111696, PEP 737: Add PyType_GetModuleName() function (#116824) 2024-03-14 18:17:43 +00:00
svnmap.txt
valgrind-python.supp
vgrindefs

Python Misc subdirectory
========================

This directory contains files that wouldn't fit in elsewhere.  Some
documents are only of historic importance.

Files found here
----------------

ACKS                    Acknowledgements
HISTORY                 News from previous releases -- oldest last
indent.pro              GNU indent profile approximating my C style
NEWS                    News for this release (for some meaning of "this")
Porting                 Mini-FAQ on porting to new platforms
python-config.in        Python script template for python-config
python.man              UNIX man page for the python interpreter
python.pc.in            Package configuration info template for pkg-config
README                  The file you're reading now
README.AIX              Information about using Python on AIX
README.coverity         Information about running Coverity's Prevent on Python
README.valgrind         Information for Valgrind users, see valgrind-python.supp
SpecialBuilds.txt       Describes extra symbols you can set for debug builds
svnmap.txt              Map of old SVN revs and branches to hg changeset ids,
                        help history-digging
valgrind-python.supp    Valgrind suppression file, see README.valgrind
vgrindefs               Python configuration for vgrind (a generic pretty printer)