summaryrefslogtreecommitdiffstats
path: root/Doc/c-api/init.rst
diff options
context:
space:
mode:
authorPetr Viktorin <encukou@gmail.com>2020-01-09 12:05:18 (GMT)
committerMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2020-01-09 12:05:18 (GMT)
commit6c5d661342d12f6836580b0e75e3569c764527ae (patch)
treee835b35890c605fffb237ad3c7d78c272ed26719 /Doc/c-api/init.rst
parentf3e5e9566989635225d1b91088888074fc260817 (diff)
downloadcpython-6c5d661342d12f6836580b0e75e3569c764527ae.zip
cpython-6c5d661342d12f6836580b0e75e3569c764527ae.tar.gz
cpython-6c5d661342d12f6836580b0e75e3569c764527ae.tar.bz2
bpo-39161: Document multi-phase init modules under Py_NewInterpreter() (GH-17896)
\+ this also adds a stronger warning against sharing objects between (sub-)interpreters. https://bugs.python.org/issue39161
Diffstat (limited to 'Doc/c-api/init.rst')
-rw-r--r--Doc/c-api/init.rst52
1 files changed, 35 insertions, 17 deletions
diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst
index 3887937..8913dbf 100644
--- a/Doc/c-api/init.rst
+++ b/Doc/c-api/init.rst
@@ -1230,15 +1230,31 @@ function. You can create and destroy them using the following functions:
single: Py_FinalizeEx()
single: Py_Initialize()
- Extension modules are shared between (sub-)interpreters as follows: the first
- time a particular extension is imported, it is initialized normally, and a
- (shallow) copy of its module's dictionary is squirreled away. When the same
- extension is imported by another (sub-)interpreter, a new module is initialized
- and filled with the contents of this copy; the extension's ``init`` function is
- not called. Note that this is different from what happens when an extension is
- imported after the interpreter has been completely re-initialized by calling
- :c:func:`Py_FinalizeEx` and :c:func:`Py_Initialize`; in that case, the extension's
- ``initmodule`` function *is* called again.
+ Extension modules are shared between (sub-)interpreters as follows:
+
+ * For modules using multi-phase initialization,
+ e.g. :c:func:`PyModule_FromDefAndSpec`, a separate module object is
+ created and initialized for each interpreter.
+ Only C-level static and global variables are shared between these
+ module objects.
+
+ * For modules using single-phase initialization,
+ e.g. :c:func:`PyModule_Create`, the first time a particular extension
+ is imported, it is initialized normally, and a (shallow) copy of its
+ module's dictionary is squirreled away.
+ When the same extension is imported by another (sub-)interpreter, a new
+ module is initialized and filled with the contents of this copy; the
+ extension's ``init`` function is not called.
+ Objects in the module's dictionary thus end up shared across
+ (sub-)interpreters, which might cause unwanted behavior (see
+ `Bugs and caveats`_ below).
+
+ Note that this is different from what happens when an extension is
+ imported after the interpreter has been completely re-initialized by
+ calling :c:func:`Py_FinalizeEx` and :c:func:`Py_Initialize`; in that
+ case, the extension's ``initmodule`` function *is* called again.
+ As with multi-phase initialization, this means that only C-level static
+ and global variables are shared between these modules.
.. index:: single: close() (in module os)
@@ -1264,14 +1280,16 @@ process, the insulation between them isn't perfect --- for example, using
low-level file operations like :func:`os.close` they can
(accidentally or maliciously) affect each other's open files. Because of the
way extensions are shared between (sub-)interpreters, some extensions may not
-work properly; this is especially likely when the extension makes use of
-(static) global variables, or when the extension manipulates its module's
-dictionary after its initialization. It is possible to insert objects created
-in one sub-interpreter into a namespace of another sub-interpreter; this should
-be done with great care to avoid sharing user-defined functions, methods,
-instances or classes between sub-interpreters, since import operations executed
-by such objects may affect the wrong (sub-)interpreter's dictionary of loaded
-modules.
+work properly; this is especially likely when using single-phase initialization
+or (static) global variables.
+It is possible to insert objects created in one sub-interpreter into
+a namespace of another (sub-)interpreter; this should be avoided if possible.
+
+Special care should be taken to avoid sharing user-defined functions,
+methods, instances or classes between sub-interpreters, since import
+operations executed by such objects may affect the wrong (sub-)interpreter's
+dictionary of loaded modules. It is equally important to avoid sharing
+objects from which the above are reachable.
Also note that combining this functionality with :c:func:`PyGILState_\*` APIs
is delicate, because these APIs assume a bijection between Python thread states