Skip to content

Commit 73cccbb

Browse files
committed
Document the new APIs.
1 parent 722dbdf commit 73cccbb

3 files changed

Lines changed: 521 additions & 160 deletions

File tree

Doc/c-api/interp-lifecycle.rst

Lines changed: 185 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -578,31 +578,195 @@ Initializing and finalizing the interpreter
578578
579579
.. _cautions-regarding-runtime-finalization:
580580
581-
Cautions regarding runtime finalization
582-
---------------------------------------
581+
Cautions regarding interpreter finalization
582+
-------------------------------------------
583583
584584
In the late stage of :term:`interpreter shutdown`, after attempting to wait for
585585
non-daemon threads to exit (though this can be interrupted by
586586
:class:`KeyboardInterrupt`) and running the :mod:`atexit` functions, the runtime
587-
is marked as *finalizing*: :c:func:`Py_IsFinalizing` and
588-
:func:`sys.is_finalizing` return true. At this point, only the *finalization
589-
thread* that initiated finalization (typically the main thread) is allowed to
590-
acquire the :term:`GIL`.
591-
592-
If any thread, other than the finalization thread, attempts to attach a :term:`thread state`
593-
during finalization, either explicitly or
594-
implicitly, the thread enters **a permanently blocked state**
595-
where it remains until the program exits. In most cases this is harmless, but this can result
596-
in deadlock if a later stage of finalization attempts to acquire a lock owned by the
597-
blocked thread, or otherwise waits on the blocked thread.
598-
599-
Gross? Yes. This prevents random crashes and/or unexpectedly skipped C++
600-
finalizations further up the call stack when such threads were forcibly exited
601-
here in CPython 3.13 and earlier. The CPython runtime :term:`thread state` C APIs
602-
have never had any error reporting or handling expectations at :term:`thread state`
603-
attachment time that would've allowed for graceful exit from this situation. Changing that
604-
would require new stable C APIs and rewriting the majority of C code in the
605-
CPython ecosystem to use those with error handling.
587+
is marked as finalizing, meaning that :c:func:`Py_IsFinalizing` and
588+
:func:`sys.is_finalizing` return true. At this point, only the finalization
589+
thread (the thread that initiated finalization; this is typically the main thread)
590+
is allowed to :term:`attach <attached thread state>` a thread state.
591+
592+
Other threads that attempt to attach during finalization, either explicitly
593+
(such as via :c:func:`PyThreadState_Ensure` or :c:macro:`Py_END_ALLOW_THREADS`)
594+
or implicitly (such as in-between bytecode instructions), will enter a
595+
**permanently blocked state**. Generally, this is harmless, but this can
596+
result in deadlocks. For example, a thread may be permanently blocked while
597+
holding a lock, meaning that the finalization thread can never acquire that
598+
lock.
599+
600+
Prior to CPython 3.13, the thread would exit instead of hanging,
601+
which led to other issues (see the warning note at
602+
:c:func:`PyThread_exit_thread`).
603+
604+
Gross? Yes. Starting in Python 3.15, there are a number of C APIs that make
605+
it possible to avoid these issues by temporarily preventing finalization:
606+
607+
.. seealso::
608+
609+
:pep:`788`
610+
611+
.. c:type:: PyInterpreterGuard
612+
613+
An opaque interpreter guard structure.
614+
615+
By holding an interpreter guard, the caller can ensure that the interpreter
616+
will not finalize until the guard is closed (through
617+
:c:func:`PyInterpreterGuard_Close`).
618+
619+
When a guard is held, a thread attempting to finalize the interpreter will
620+
have to wait until the guard is closed before threads can be blocked.
621+
After finalization has started, threads are forever unable to acquire
622+
guards for that interpreter. This means that if you forget to close an
623+
interpreter guard, the process will **permanently hang** during
624+
finalization!
625+
626+
.. versionadded:: next
627+
628+
629+
.. c:function:: PyInterpreterGuard *PyInterpreterGuard_FromCurrent(void)
630+
631+
Create a finalization guard for the current interpreter. This will prevent
632+
finalization from occuring until the guard is closed.
633+
634+
For example:
635+
636+
.. code-block:: c
637+
638+
// Temporarily prevent finalization.
639+
PyInterpreterGuard *guard = PyInterpreterGuard_FromCurrent();
640+
if (guard == NULL) {
641+
// Finalization has already started or we're out of memory.
642+
return NULL;
643+
}
644+
645+
Py_BEGIN_ALLOW_THREADS;
646+
// Do some critical processing here. For example, we can safely acquire
647+
// locks that might be acquired by the finalization thread.
648+
Py_END_ALLOW_THREADS;
649+
650+
// Now that we're done with our critical processing, the interpreter is
651+
// allowed to finalize again.
652+
PyInterpreterGuard_Close(guard);
653+
654+
On success, this function returns a guard for the current interpreter;
655+
on failure, it returns ``NULL`` with an exception set.
656+
657+
This function will fail only if the current interpreter has already started
658+
finalizing, or if the process is out of memory.
659+
660+
The guard pointer returned by this function must be eventually closed
661+
with :c:func:`PyInterpreterGuard_Close`; failing to do so will result in
662+
the Python process infinitely hanging.
663+
664+
The caller must hold an :term:`attached thread state`.
665+
666+
.. versionadded:: next
667+
668+
669+
.. c:function:: PyInterpreterGuard *PyInterpreterGuard_FromView(PyInterpreterView *view)
670+
671+
Create a finalization guard for an interpreter through a view.
672+
673+
On success, this function returns a guard to the interpreter
674+
represented by *view*. The view is still valid after calling this
675+
function. The guard must eventually be closed with
676+
:c:func:`PyInterpreterGuard_Close`.
677+
678+
If the interpreter no longer exists, is already finalizing, or out of memory,
679+
then this function returns ``NULL`` without setting an exception.
680+
681+
The caller does not need to hold an :term:`attached thread state`.
682+
683+
.. versionadded:: next
684+
685+
686+
.. c:function:: void PyInterpreterGuard_Close(PyInterpreterGuard *guard)
687+
688+
Close an interpreter guard, allowing the interpreter to start
689+
finalization if no other guards remain. If an interpreter guard
690+
is never closed, the interpreter will infinitely wait when trying
691+
to enter finalization!
692+
693+
After an interpreter guard is closed, it may not be used in
694+
:c:func:`PyThreadState_Ensure`. Doing so will result in undefined
695+
behavior.
696+
697+
Currently, this function will deallocate *guard*, but this may change in
698+
the future.
699+
700+
This function cannot fail, and the caller doesn't need to hold an
701+
:term:`attached thread state`.
702+
703+
.. versionadded:: next
704+
705+
706+
Interpreter views
707+
-----------------
708+
709+
In some cases, it may be necessary to access an interpreter that may have been
710+
deleted. This can be done using interpreter views.
711+
712+
.. c:type:: PyInterpreterView
713+
714+
An opaque view of an interpreter.
715+
716+
This is a thread-safe way to access an interpreter that may have be
717+
finalizing or already destroyed.
718+
719+
.. versionadded:: next
720+
721+
722+
.. c:function:: PyInterpreterView *PyInterpreterView_FromCurrent(void)
723+
724+
Create a view to the current interpreter.
725+
726+
This function is generally meant to be used alongside
727+
:c:func:`PyInterpreterGuard_FromView` or :c:func:`PyThreadState_EnsureFromView`.
728+
729+
On success, this function returns a view to the current interpreter; on
730+
failure, it returns ``NULL`` with an exception set.
731+
732+
The caller must hold an :term:`attached thread state`.
733+
734+
.. versionadded:: next
735+
736+
737+
.. c:function:: void PyInterpreterView_Close(PyInterpreterView *view)
738+
739+
Close an interpreter view.
740+
741+
If an interpreter view is never closed, the view's memory will never be
742+
freed, but there are no other consequences. (In contrast, forgetting to
743+
close a guard will infinitely hang the main thread during finalization.)
744+
745+
Currently, this function will deallocate *view*, but this may change in
746+
the future.
747+
748+
This function cannot fail, and the caller doesn't need to hold an
749+
:term:`attached thread state`.
750+
751+
752+
.. c:function:: PyInterpreterView *PyInterpreterView_FromMain()
753+
754+
Create a view for the main interpreter (the first and default
755+
interpreter in a Python process; see
756+
:c:func:`PyInterpreterState_Main`).
757+
758+
On success, this function returns a view to the main
759+
interpreter; on failure, it returns ``NULL`` without an exception set.
760+
Failure indicates that the process is out of memory or that the main
761+
interpreter has finalized (or never existed).
762+
763+
Generally speaking, using this function is strongly discouraged, because
764+
it typically compromises subinterpreter support for a program. It exists
765+
for exceptional cases where there is no other option (such as when a native
766+
threading library doesn't provide a ``void *arg`` parameter that could be
767+
used to store a ``PyInterpreterGuard`` or ``PyInterpreterView`` pointer).
768+
769+
The caller does not need to hold an :term:`attached thread state`.
606770
607771
608772
Process-wide parameters

0 commit comments

Comments
 (0)