@@ -571,6 +571,35 @@ Initializing and finalizing the interpreter
571571 .. versionadded :: 3.13
572572
573573
574+ .. _cautions-regarding-runtime-finalization :
575+
576+ Cautions regarding runtime finalization
577+ ---------------------------------------
578+
579+ In the late stage of :term: `interpreter shutdown `, after attempting to wait for
580+ non-daemon threads to exit (though this can be interrupted by
581+ :class: `KeyboardInterrupt `) and running the :mod:`atexit` functions, the runtime
582+ is marked as *finalizing*: :c:func:`Py_IsFinalizing` and
583+ :func:`sys.is_finalizing` return true. At this point, only the *finalization
584+ thread* that initiated finalization (typically the main thread) is allowed to
585+ acquire the :term:`GIL`.
586+
587+ If any thread, other than the finalization thread, attempts to attach a :term:`thread state`
588+ during finalization, either explicitly or
589+ implicitly, the thread enters **a permanently blocked state**
590+ where it remains until the program exits. In most cases this is harmless, but this can result
591+ in deadlock if a later stage of finalization attempts to acquire a lock owned by the
592+ blocked thread, or otherwise waits on the blocked thread.
593+
594+ Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++
595+ finalizations further up the call stack when such threads were forcibly exited
596+ here in CPython 3.13 and earlier. The CPython runtime :term:`thread state` C APIs
597+ have never had any error reporting or handling expectations at :term:`thread state`
598+ attachment time that would've allowed for graceful exit from this situation. Changing that
599+ would require new stable C APIs and rewriting the majority of C code in the
600+ CPython ecosystem to use those with error handling.
601+
602+
574603Process-wide parameters
575604-----------------------
576605
@@ -769,32 +798,3 @@ Process-wide parameters
769798 :c:expr:`wchar_t*` string.
770799
771800 .. deprecated-removed:: 3.11 3.15
772-
773-
774- .. _cautions-regarding-runtime-finalization:
775-
776- Cautions regarding runtime finalization
777- ---------------------------------------
778-
779- In the late stage of :term:`interpreter shutdown`, after attempting to wait for
780- non-daemon threads to exit (though this can be interrupted by
781- :class:`KeyboardInterrupt`) and running the :mod:`atexit` functions, the runtime
782- is marked as *finalizing*: :c:func:`Py_IsFinalizing` and
783- :func:`sys.is_finalizing` return true. At this point, only the *finalization
784- thread* that initiated finalization (typically the main thread) is allowed to
785- acquire the :term:`GIL`.
786-
787- If any thread, other than the finalization thread, attempts to attach a :term:`thread state`
788- during finalization, either explicitly or
789- implicitly, the thread enters **a permanently blocked state**
790- where it remains until the program exits. In most cases this is harmless, but this can result
791- in deadlock if a later stage of finalization attempts to acquire a lock owned by the
792- blocked thread, or otherwise waits on the blocked thread.
793-
794- Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++
795- finalizations further up the call stack when such threads were forcibly exited
796- here in CPython 3.13 and earlier. The CPython runtime :term:`thread state` C APIs
797- have never had any error reporting or handling expectations at :term:`thread state`
798- attachment time that would've allowed for graceful exit from this situation. Changing that
799- would require new stable C APIs and rewriting the majority of C code in the
800- CPython ecosystem to use those with error handling.
0 commit comments