mirror of
https://github.com/python/cpython.git
synced 2025-08-21 09:21:18 +00:00
bpo-44050: Extension modules can share state when they don't support sub-interpreters. (GH-27794) (GH-28738)
Automerge-Triggered-By: GH:encukou
(cherry picked from commit b9bb74871b
)
Co-authored-by: Hai Shi <shihai1992@gmail.com>
This commit is contained in:
parent
d0d0909a3a
commit
d0d29655ff
4 changed files with 59 additions and 1 deletions
|
@ -762,6 +762,37 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
|
|
||||||
self.assertFalse(hasattr(binascii.Error, "foobar"))
|
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):
|
class TestThreadState(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -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.
|
|
@ -844,6 +844,28 @@ PyInit__testmultiphase_meth_state_access(PyObject *spec)
|
||||||
return PyModuleDef_Init(&def_meth_state_access);
|
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 ***/
|
/*** Helper for imp test ***/
|
||||||
|
|
||||||
|
|
|
@ -441,7 +441,9 @@ _PyImport_FixupExtensionObject(PyObject *mod, PyObject *name,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Py_IsMainInterpreter(tstate->interp)) {
|
// 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->interp) || def->m_size == -1) {
|
||||||
if (def->m_size == -1) {
|
if (def->m_size == -1) {
|
||||||
if (def->m_base.m_copy) {
|
if (def->m_base.m_copy) {
|
||||||
/* Somebody already imported the module,
|
/* Somebody already imported the module,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue