From 4ffadb4430b6cda726473b72c98bcd7c3b35a17f Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Tue, 17 Aug 2021 17:37:21 +0800 Subject: [PATCH 1/5] Extension modules created from PyModule_Create() can share state --- Python/import.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Python/import.c b/Python/import.c index 7301fccb9fac0c..cc7d6b051e31ff 100644 --- a/Python/import.c +++ b/Python/import.c @@ -441,7 +441,9 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, return -1; } - if (_Py_IsMainInterpreter(tstate->interp)) { + // bpo-44050: Extensions and def->m_base.m_copy can be updated + // when extension module created from PyModule_Create(). + if (_Py_IsMainInterpreter(tstate->interp) || def->m_slots == NULL) { if (def->m_size == -1) { if (def->m_base.m_copy) { /* Somebody already imported the module, From 2d2165cdfa0c6b3aa97ea577537f4afab3d65f8a Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Tue, 17 Aug 2021 22:19:51 +0800 Subject: [PATCH 2/5] apply petr's comment --- Python/import.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/import.c b/Python/import.c index cc7d6b051e31ff..a4340d4b3935d5 100644 --- a/Python/import.c +++ b/Python/import.c @@ -442,8 +442,8 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name, } // bpo-44050: Extensions and def->m_base.m_copy can be updated - // when extension module created from PyModule_Create(). - if (_Py_IsMainInterpreter(tstate->interp) || def->m_slots == NULL) { + // when the extension module doesn't support sub-interpreters. + if (_Py_IsMainInterpreter(tstate->interp) || def->m_size == -1) { if (def->m_size == -1) { if (def->m_base.m_copy) { /* Somebody already imported the module, From 70b7861b0dc76756f599cd4f25830437102cb7a0 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Sat, 21 Aug 2021 16:57:46 +0800 Subject: [PATCH 3/5] apply victor's comment --- Lib/test/test_capi.py | 31 +++++++++++++++++++++++++++++++ Modules/_testmultiphase.c | 22 ++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 9165f45db64f34..39a93d3233a539 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -754,6 +754,37 @@ def test_mutate_exception(self): 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/Modules/_testmultiphase.c b/Modules/_testmultiphase.c index ad60f32f7e7a62..e0ed77d265cdcc 100644 --- a/Modules/_testmultiphase.c +++ b/Modules/_testmultiphase.c @@ -844,6 +844,28 @@ 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; + } + + if (PyModule_AddObjectRef(module, "Error", PyExc_Exception) < 0) { + Py_DECREF(module); + return NULL; + } + return module; +} + /*** Helper for imp test ***/ From d53e2dd4a8bb9c8aeb55b880ee43bb586c137e79 Mon Sep 17 00:00:00 2001 From: Hai Shi Date: Wed, 8 Sep 2021 00:34:29 +0800 Subject: [PATCH 4/5] add a NEWS entry --- .../Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst 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 00000000000000..3350ef5738cac5 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst @@ -0,0 +1,2 @@ +Extensions and def->m_base.m_copy can be updated when the extension module +doesn't support sub-interpreters. From eb9b40d4ab99cc658152b105965d0f10885ca2f2 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Tue, 5 Oct 2021 14:56:31 +0200 Subject: [PATCH 5/5] Update Misc/NEWS.d/next/Core and Builtins/2021-09-08-00-30-09.bpo-44050.mFI15u.rst --- .../2021-09-08-00-30-09.bpo-44050.mFI15u.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 index 3350ef5738cac5..d6eed9f1bcfe9d 100644 --- 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 @@ -1,2 +1,3 @@ -Extensions and def->m_base.m_copy can be updated when the extension module -doesn't support sub-interpreters. +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.