mirror of
https://github.com/python/cpython.git
synced 2025-08-02 16:13:13 +00:00
gh-99113: Add a check for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED (gh-104206)
Py_MOD_PER_INTERPRETER_GIL_SUPPORTED is a new supported value for Py_mod_multiple_interpreters, added in gh-104205.
This commit is contained in:
parent
3b14b51d11
commit
fff193bbfe
5 changed files with 99 additions and 2 deletions
|
@ -1861,6 +1861,26 @@ class SubinterpImportTests(unittest.TestCase):
|
||||||
with self.subTest(f'{modname}: not strict'):
|
with self.subTest(f'{modname}: not strict'):
|
||||||
self.check_compatible_here(modname, filename, strict=False)
|
self.check_compatible_here(modname, filename, strict=False)
|
||||||
|
|
||||||
|
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
||||||
|
def test_multi_init_extension_per_interpreter_gil_compat(self):
|
||||||
|
modname = '_test_shared_gil_only'
|
||||||
|
filename = _testmultiphase.__file__
|
||||||
|
loader = ExtensionFileLoader(modname, filename)
|
||||||
|
spec = importlib.util.spec_from_loader(modname, loader)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
loader.exec_module(module)
|
||||||
|
sys.modules[modname] = module
|
||||||
|
|
||||||
|
require_extension(module)
|
||||||
|
with self.subTest(f'{modname}: isolated, strict'):
|
||||||
|
self.check_incompatible_here(modname, filename, isolated=True)
|
||||||
|
with self.subTest(f'{modname}: not isolated, strict'):
|
||||||
|
self.check_compatible_here(modname, filename,
|
||||||
|
strict=True, isolated=False)
|
||||||
|
with self.subTest(f'{modname}: not isolated, not strict'):
|
||||||
|
self.check_compatible_here(modname, filename,
|
||||||
|
strict=False, isolated=False)
|
||||||
|
|
||||||
def test_python_compat(self):
|
def test_python_compat(self):
|
||||||
module = 'threading'
|
module = 'threading'
|
||||||
require_pure_python(module)
|
require_pure_python(module)
|
||||||
|
|
|
@ -348,6 +348,8 @@ class MultiPhaseExtensionModuleTests(abc.LoaderTests):
|
||||||
'exec_err',
|
'exec_err',
|
||||||
'exec_raise',
|
'exec_raise',
|
||||||
'exec_unreported_exception',
|
'exec_unreported_exception',
|
||||||
|
'multiple_create_slots',
|
||||||
|
'multiple_multiple_interpreters_slots',
|
||||||
]:
|
]:
|
||||||
with self.subTest(name_base):
|
with self.subTest(name_base):
|
||||||
name = self.name + '_' + name_base
|
name = self.name + '_' + name_base
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
Multi-phase init extension modules may now indicate that they support
|
||||||
|
running in subinterpreters that have their own GIL. This is done by using
|
||||||
|
``Py_MOD_PER_INTERPRETER_GIL_SUPPORTED`` as the value for the
|
||||||
|
``Py_mod_multiple_interpreters`` module def slot. Otherwise the module, by
|
||||||
|
default, cannot be imported in such subinterpreters. (This does not affect
|
||||||
|
the main interpreter or subinterpreters that do not have their own GIL.) In
|
||||||
|
addition to the isolation that multi-phase init already normally requires,
|
||||||
|
support for per-interpreter GIL involves one additional constraint:
|
||||||
|
thread-safety. If the module has external (linked) dependencies and those
|
||||||
|
libraries have any state that isn't thread-safe then the module must do the
|
||||||
|
additional work to add thread-safety. This should be an uncommon case.
|
|
@ -681,6 +681,27 @@ PyInit__testmultiphase_export_unreported_exception(void)
|
||||||
return PyModuleDef_Init(&main_def);
|
return PyModuleDef_Init(&main_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
createfunc_noop(PyObject *spec, PyModuleDef *def)
|
||||||
|
{
|
||||||
|
return PyModule_New("spam");
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyModuleDef_Slot slots_multiple_create_slots[] = {
|
||||||
|
{Py_mod_create, createfunc_noop},
|
||||||
|
{Py_mod_create, createfunc_noop},
|
||||||
|
{0, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyModuleDef def_multiple_create_slots = TEST_MODULE_DEF(
|
||||||
|
"_testmultiphase_multiple_create_slots", slots_multiple_create_slots, NULL);
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
PyInit__testmultiphase_multiple_create_slots(void)
|
||||||
|
{
|
||||||
|
return PyModuleDef_Init(&def_multiple_create_slots);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
createfunc_null(PyObject *spec, PyModuleDef *def)
|
createfunc_null(PyObject *spec, PyModuleDef *def)
|
||||||
{
|
{
|
||||||
|
@ -892,7 +913,24 @@ PyInit__test_module_state_shared(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* multiple interpreters supports */
|
/* multiple interpreters support */
|
||||||
|
|
||||||
|
static PyModuleDef_Slot slots_multiple_multiple_interpreters_slots[] = {
|
||||||
|
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
|
||||||
|
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
|
||||||
|
{0, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyModuleDef def_multiple_multiple_interpreters_slots = TEST_MODULE_DEF(
|
||||||
|
"_testmultiphase_multiple_multiple_interpreters_slots",
|
||||||
|
slots_multiple_multiple_interpreters_slots,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
PyInit__testmultiphase_multiple_multiple_interpreters_slots(void)
|
||||||
|
{
|
||||||
|
return PyModuleDef_Init(&def_multiple_multiple_interpreters_slots);
|
||||||
|
}
|
||||||
|
|
||||||
static PyModuleDef_Slot non_isolated_slots[] = {
|
static PyModuleDef_Slot non_isolated_slots[] = {
|
||||||
{Py_mod_exec, execfunc},
|
{Py_mod_exec, execfunc},
|
||||||
|
@ -909,3 +947,23 @@ PyInit__test_non_isolated(void)
|
||||||
{
|
{
|
||||||
return PyModuleDef_Init(&non_isolated_def);
|
return PyModuleDef_Init(&non_isolated_def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyModuleDef_Slot shared_gil_only_slots[] = {
|
||||||
|
{Py_mod_exec, execfunc},
|
||||||
|
/* Note that Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED is the default.
|
||||||
|
We put it here explicitly to draw attention to the contrast
|
||||||
|
with Py_MOD_PER_INTERPRETER_GIL_SUPPORTED. */
|
||||||
|
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED},
|
||||||
|
{0, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyModuleDef shared_gil_only_def = TEST_MODULE_DEF("_test_shared_gil_only",
|
||||||
|
shared_gil_only_slots,
|
||||||
|
testexport_methods);
|
||||||
|
|
||||||
|
PyMODINIT_FUNC
|
||||||
|
PyInit__test_shared_gil_only(void)
|
||||||
|
{
|
||||||
|
return PyModuleDef_Init(&shared_gil_only_def);
|
||||||
|
}
|
||||||
|
|
|
@ -323,7 +323,13 @@ PyModule_FromDefAndSpec2(PyModuleDef* def, PyObject *spec, int module_api_versio
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// XXX Do a similar check once we have PyInterpreterState.ceval.own_gil.
|
else if (multiple_interpreters != Py_MOD_PER_INTERPRETER_GIL_SUPPORTED
|
||||||
|
&& interp->ceval.own_gil
|
||||||
|
&& !_Py_IsMainInterpreter(interp)
|
||||||
|
&& _PyImport_CheckSubinterpIncompatibleExtensionAllowed(name) < 0)
|
||||||
|
{
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (create) {
|
if (create) {
|
||||||
m = create(spec, def);
|
m = create(spec, def);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue