Skip to content

Commit 7a5d4c7

Browse files
bpo-38816: Add notes in the C-API docs about fork in subinterpreters. (GH-17176)
The C-API docs are a bit sparse on the interplay between C `fork()` and the CPython runtime. This change adds some more information on the subject. https://bugs.python.org/issue38816 (cherry picked from commit 73cdb0c) Co-authored-by: Eric Snow <[email protected]>
1 parent 25ce77d commit 7a5d4c7

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

Doc/c-api/init.rst

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,9 +769,19 @@ supports the creation of additional interpreters (using
769769
:c:func:`Py_NewInterpreter`), but mixing multiple interpreters and the
770770
:c:func:`PyGILState_\*` API is unsupported.
771771
772+
773+
.. _fork-and-threads:
774+
775+
Cautions about fork()
776+
---------------------
777+
772778
Another important thing to note about threads is their behaviour in the face
773779
of the C :c:func:`fork` call. On most systems with :c:func:`fork`, after a
774-
process forks only the thread that issued the fork will exist. That also
780+
process forks only the thread that issued the fork will exist. This has a
781+
concrete impact both on how locks must be handled and on all stored state
782+
in CPython's runtime.
783+
784+
The fact that only the "current" thread remains
775785
means any locks held by other threads will never be released. Python solves
776786
this for :func:`os.fork` by acquiring the locks it uses internally before
777787
the fork, and releasing them afterwards. In addition, it resets any
@@ -786,6 +796,17 @@ being held by a thread that is defunct after the fork.
786796
:c:func:`PyOS_AfterFork_Child` tries to reset the necessary locks, but is not
787797
always able to.
788798
799+
The fact that all other threads go away also means that CPython's
800+
runtime state there must be cleaned up properly, which :func:`os.fork`
801+
does. This means finalizing all other :c:type:`PyThreadState` objects
802+
belonging to the current interpreter and all other
803+
:c:type:`PyInterpreterState` objects. Due to this and the special
804+
nature of the :ref:`"main" interpreter <sub-interpreter-support>`,
805+
:c:func:`fork` should only be called in that interpreter's "main"
806+
thread, where the CPython global runtime was originally initialized.
807+
The only exception is if :c:func:`exec` will be called immediately
808+
after.
809+
789810
790811
High-level API
791812
--------------

Doc/c-api/sys.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ Operating System Utilities
3333
that clones the current process.
3434
Only available on systems where :c:func:`fork` is defined.
3535
36+
.. warning::
37+
The C :c:func:`fork` call should only be made from the
38+
:ref:`"main" thread <fork-and-threads>` (of the
39+
:ref:`"main" interpreter <sub-interpreter-support>`). The same is
40+
true for ``PyOS_BeforeFork()``.
41+
3642
.. versionadded:: 3.7
3743
3844
@@ -44,6 +50,12 @@ Operating System Utilities
4450
of whether process cloning was successful.
4551
Only available on systems where :c:func:`fork` is defined.
4652
53+
.. warning::
54+
The C :c:func:`fork` call should only be made from the
55+
:ref:`"main" thread <fork-and-threads>` (of the
56+
:ref:`"main" interpreter <sub-interpreter-support>`). The same is
57+
true for ``PyOS_AfterFork_Parent()``.
58+
4759
.. versionadded:: 3.7
4860
4961
@@ -55,6 +67,12 @@ Operating System Utilities
5567
any chance the process will call back into the Python interpreter.
5668
Only available on systems where :c:func:`fork` is defined.
5769
70+
.. warning::
71+
The C :c:func:`fork` call should only be made from the
72+
:ref:`"main" thread <fork-and-threads>` (of the
73+
:ref:`"main" interpreter <sub-interpreter-support>`). The same is
74+
true for ``PyOS_AfterFork_Child()``.
75+
5876
.. versionadded:: 3.7
5977
6078
.. seealso::
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Provides more details about the interaction between :c:func:`fork` and
2+
CPython's runtime, focusing just on the C-API. This includes cautions
3+
about where :c:func:`fork` should and shouldn't be called.

0 commit comments

Comments
 (0)