summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorƁukasz Langa <lukasz@langa.pl>2021-10-05 20:30:25 (GMT)
committerGitHub <noreply@github.com>2021-10-05 20:30:25 (GMT)
commit52d9d3b75441ae6038fadead89eac5eecdd34501 (patch)
tree8d779959a1d0da0eb29bbfe7046d2a643e1ca93b
parent950b324973a98ec45c21e7e7149415259a045ff7 (diff)
downloadcpython-52d9d3b75441ae6038fadead89eac5eecdd34501.zip
cpython-52d9d3b75441ae6038fadead89eac5eecdd34501.tar.gz
cpython-52d9d3b75441ae6038fadead89eac5eecdd34501.tar.bz2
[3.9] bpo-44050: Extension modules can share state when they don't support sub-interpreters. (GH-27794) (GH-28741)
(cherry picked from commit b9bb74871b27d9226df2dd3fce9d42bda8b43c2b) Co-authored-by: Hai Shi <shihai1992@gmail.com>
-rw-r--r--Lib/test/test_capi.py31
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst3
-rw-r--r--Modules/_testmultiphase.c24
-rw-r--r--Python/import.c4
4 files changed, 61 insertions, 1 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 0cbe839..6b2fe2f 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -680,6 +680,37 @@ class SubinterpreterTest(unittest.TestCase):
self.assertFalse(hasattr(binascii.Error, "foobar"))
+ def test_module_state_shared_in_global(self):
+ """
+ bpo-44050: Extension module state should be shared between interpreters
+ when it doesn't support sub-interpreters.
+ """
+ r, w = os.pipe()
+ self.addCleanup(os.close, r)
+ self.addCleanup(os.close, w)
+
+ script = textwrap.dedent(f"""
+ import importlib.machinery
+ import importlib.util
+ import os
+
+ fullname = '_test_module_state_shared'
+ origin = importlib.util.find_spec('_testmultiphase').origin
+ loader = importlib.machinery.ExtensionFileLoader(fullname, origin)
+ spec = importlib.util.spec_from_loader(fullname, loader)
+ module = importlib.util.module_from_spec(spec)
+ attr_id = str(id(module.Error)).encode()
+
+ os.write({w}, attr_id)
+ """)
+ exec(script)
+ main_attr_id = os.read(r, 100)
+
+ ret = support.run_in_subinterp(script)
+ self.assertEqual(ret, 0)
+ subinterp_attr_id = os.read(r, 100)
+ self.assertEqual(main_attr_id, subinterp_attr_id)
+
class TestThreadState(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst
new file mode 100644
index 0000000..d6eed9f
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst
@@ -0,0 +1,3 @@
+Extensions that indicate they use global state (by setting ``m_size`` to -1)
+can again be used in multiple interpreters. This reverts to behavior of
+Python 3.8.
diff --git a/Modules/_testmultiphase.c b/Modules/_testmultiphase.c
index d69ae62..4a4dbe7 100644
--- a/Modules/_testmultiphase.c
+++ b/Modules/_testmultiphase.c
@@ -834,6 +834,30 @@ PyInit__testmultiphase_meth_state_access(PyObject *spec)
return PyModuleDef_Init(&def_meth_state_access);
}
+static PyModuleDef def_module_state_shared = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_test_module_state_shared",
+ .m_doc = PyDoc_STR("Regression Test module for single-phase init."),
+ .m_size = -1,
+};
+
+PyMODINIT_FUNC
+PyInit__test_module_state_shared(PyObject *spec)
+{
+ PyObject *module = PyModule_Create(&def_module_state_shared);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ Py_INCREF(PyExc_Exception);
+ if (PyModule_AddObject(module, "Error", PyExc_Exception) < 0) {
+ Py_DECREF(PyExc_Exception);
+ Py_DECREF(module);
+ return NULL;
+ }
+ return module;
+}
+
/*** Helper for imp test ***/
diff --git a/Python/import.c b/Python/import.c
index 1ec7553..8358d70 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -710,7 +710,9 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,
return -1;
}
- if (_Py_IsMainInterpreter(tstate)) {
+ // bpo-44050: Extensions and def->m_base.m_copy can be updated
+ // when the extension module doesn't support sub-interpreters.
+ if (_Py_IsMainInterpreter(tstate) || def->m_size == -1) {
if (def->m_size == -1) {
if (def->m_base.m_copy) {
/* Somebody already imported the module,