mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
gh-117649: Raise ImportError for unsupported modules in free-threaded build (#117651)
The free-threaded build does not currently support the combination of single-phase init modules and non-isolated subinterpreters. Ensure that `check_multi_interp_extensions` is always `True` for subinterpreters in the free-threaded build so that importing these modules raises an `ImportError`.
This commit is contained in:
parent
39d381f91e
commit
25f6ff5d3e
9 changed files with 103 additions and 32 deletions
|
@ -63,6 +63,15 @@ typedef struct {
|
||||||
.gil = PyInterpreterConfig_OWN_GIL, \
|
.gil = PyInterpreterConfig_OWN_GIL, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-117649: The free-threaded build does not currently support single-phase
|
||||||
|
// init extensions in subinterpreters. For now, we ensure that
|
||||||
|
// `check_multi_interp_extensions` is always `1`, even in the legacy config.
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
# define _PyInterpreterConfig_LEGACY_CHECK_MULTI_INTERP_EXTENSIONS 1
|
||||||
|
#else
|
||||||
|
# define _PyInterpreterConfig_LEGACY_CHECK_MULTI_INTERP_EXTENSIONS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define _PyInterpreterConfig_LEGACY_INIT \
|
#define _PyInterpreterConfig_LEGACY_INIT \
|
||||||
{ \
|
{ \
|
||||||
.use_main_obmalloc = 1, \
|
.use_main_obmalloc = 1, \
|
||||||
|
@ -70,7 +79,7 @@ typedef struct {
|
||||||
.allow_exec = 1, \
|
.allow_exec = 1, \
|
||||||
.allow_threads = 1, \
|
.allow_threads = 1, \
|
||||||
.allow_daemon_threads = 1, \
|
.allow_daemon_threads = 1, \
|
||||||
.check_multi_interp_extensions = 0, \
|
.check_multi_interp_extensions = _PyInterpreterConfig_LEGACY_CHECK_MULTI_INTERP_EXTENSIONS, \
|
||||||
.gil = PyInterpreterConfig_SHARED_GIL, \
|
.gil = PyInterpreterConfig_SHARED_GIL, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -842,6 +842,12 @@ def requires_gil_enabled(msg="needs the GIL enabled"):
|
||||||
"""Decorator for skipping tests on the free-threaded build."""
|
"""Decorator for skipping tests on the free-threaded build."""
|
||||||
return unittest.skipIf(Py_GIL_DISABLED, msg)
|
return unittest.skipIf(Py_GIL_DISABLED, msg)
|
||||||
|
|
||||||
|
def expected_failure_if_gil_disabled():
|
||||||
|
"""Expect test failure if the GIL is disabled."""
|
||||||
|
if Py_GIL_DISABLED:
|
||||||
|
return unittest.expectedFailure
|
||||||
|
return lambda test_case: test_case
|
||||||
|
|
||||||
if Py_GIL_DISABLED:
|
if Py_GIL_DISABLED:
|
||||||
_header = 'PHBBInP'
|
_header = 'PHBBInP'
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -26,6 +26,8 @@ from test.support import import_helper
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper
|
||||||
from test.support import warnings_helper
|
from test.support import warnings_helper
|
||||||
from test.support import requires_limited_api
|
from test.support import requires_limited_api
|
||||||
|
from test.support import requires_gil_enabled, expected_failure_if_gil_disabled
|
||||||
|
from test.support import Py_GIL_DISABLED
|
||||||
from test.support.script_helper import assert_python_failure, assert_python_ok, run_python_until_end
|
from test.support.script_helper import assert_python_failure, assert_python_ok, run_python_until_end
|
||||||
try:
|
try:
|
||||||
import _posixsubprocess
|
import _posixsubprocess
|
||||||
|
@ -2023,15 +2025,30 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
kwlist[-2] = 'check_multi_interp_extensions'
|
kwlist[-2] = 'check_multi_interp_extensions'
|
||||||
kwlist[-1] = 'own_gil'
|
kwlist[-1] = 'own_gil'
|
||||||
|
|
||||||
# expected to work
|
expected_to_work = {
|
||||||
for config, expected in {
|
|
||||||
(True, True, True, True, True, True, True):
|
(True, True, True, True, True, True, True):
|
||||||
(ALL_FLAGS, True),
|
(ALL_FLAGS, True),
|
||||||
(True, False, False, False, False, False, False):
|
(True, False, False, False, False, False, False):
|
||||||
(OBMALLOC, False),
|
(OBMALLOC, False),
|
||||||
(False, False, False, True, False, True, False):
|
(False, False, False, True, False, True, False):
|
||||||
(THREADS | EXTENSIONS, False),
|
(THREADS | EXTENSIONS, False),
|
||||||
}.items():
|
}
|
||||||
|
|
||||||
|
expected_to_fail = {
|
||||||
|
(False, False, False, False, False, False, False),
|
||||||
|
}
|
||||||
|
|
||||||
|
# gh-117649: The free-threaded build does not currently allow
|
||||||
|
# setting check_multi_interp_extensions to False.
|
||||||
|
if Py_GIL_DISABLED:
|
||||||
|
for config in list(expected_to_work.keys()):
|
||||||
|
kwargs = dict(zip(kwlist, config))
|
||||||
|
if not kwargs['check_multi_interp_extensions']:
|
||||||
|
del expected_to_work[config]
|
||||||
|
expected_to_fail.add(config)
|
||||||
|
|
||||||
|
# expected to work
|
||||||
|
for config, expected in expected_to_work.items():
|
||||||
kwargs = dict(zip(kwlist, config))
|
kwargs = dict(zip(kwlist, config))
|
||||||
exp_flags, exp_gil = expected
|
exp_flags, exp_gil = expected
|
||||||
expected = {
|
expected = {
|
||||||
|
@ -2055,9 +2072,7 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
self.assertEqual(settings, expected)
|
self.assertEqual(settings, expected)
|
||||||
|
|
||||||
# expected to fail
|
# expected to fail
|
||||||
for config in [
|
for config in expected_to_fail:
|
||||||
(False, False, False, False, False, False, False),
|
|
||||||
]:
|
|
||||||
kwargs = dict(zip(kwlist, config))
|
kwargs = dict(zip(kwlist, config))
|
||||||
with self.subTest(config):
|
with self.subTest(config):
|
||||||
script = textwrap.dedent(f'''
|
script = textwrap.dedent(f'''
|
||||||
|
@ -2070,6 +2085,9 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
|
|
||||||
@unittest.skipIf(_testsinglephase is None, "test requires _testsinglephase module")
|
@unittest.skipIf(_testsinglephase is None, "test requires _testsinglephase module")
|
||||||
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
|
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
|
||||||
|
# gh-117649: The free-threaded build does not currently allow overriding
|
||||||
|
# the check_multi_interp_extensions setting.
|
||||||
|
@expected_failure_if_gil_disabled()
|
||||||
def test_overridden_setting_extensions_subinterp_check(self):
|
def test_overridden_setting_extensions_subinterp_check(self):
|
||||||
"""
|
"""
|
||||||
PyInterpreterConfig.check_multi_interp_extensions can be overridden
|
PyInterpreterConfig.check_multi_interp_extensions can be overridden
|
||||||
|
@ -2165,6 +2183,9 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
self.assertFalse(hasattr(binascii.Error, "foobar"))
|
self.assertFalse(hasattr(binascii.Error, "foobar"))
|
||||||
|
|
||||||
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
||||||
|
# gh-117649: The free-threaded build does not currently support sharing
|
||||||
|
# extension module state between interpreters.
|
||||||
|
@expected_failure_if_gil_disabled()
|
||||||
def test_module_state_shared_in_global(self):
|
def test_module_state_shared_in_global(self):
|
||||||
"""
|
"""
|
||||||
bpo-44050: Extension module state should be shared between interpreters
|
bpo-44050: Extension module state should be shared between interpreters
|
||||||
|
@ -2223,7 +2244,7 @@ class InterpreterConfigTests(unittest.TestCase):
|
||||||
allow_exec=True,
|
allow_exec=True,
|
||||||
allow_threads=True,
|
allow_threads=True,
|
||||||
allow_daemon_threads=True,
|
allow_daemon_threads=True,
|
||||||
check_multi_interp_extensions=False,
|
check_multi_interp_extensions=bool(Py_GIL_DISABLED),
|
||||||
gil='shared',
|
gil='shared',
|
||||||
),
|
),
|
||||||
'empty': types.SimpleNamespace(
|
'empty': types.SimpleNamespace(
|
||||||
|
@ -2386,6 +2407,8 @@ class InterpreterConfigTests(unittest.TestCase):
|
||||||
check_multi_interp_extensions=False
|
check_multi_interp_extensions=False
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
if Py_GIL_DISABLED:
|
||||||
|
invalid.append(dict(check_multi_interp_extensions=False))
|
||||||
def match(config, override_cases):
|
def match(config, override_cases):
|
||||||
ns = vars(config)
|
ns = vars(config)
|
||||||
for overrides in override_cases:
|
for overrides in override_cases:
|
||||||
|
@ -2427,6 +2450,8 @@ class InterpreterConfigTests(unittest.TestCase):
|
||||||
with self.subTest('main'):
|
with self.subTest('main'):
|
||||||
expected = _interpreters.new_config('legacy')
|
expected = _interpreters.new_config('legacy')
|
||||||
expected.gil = 'own'
|
expected.gil = 'own'
|
||||||
|
if Py_GIL_DISABLED:
|
||||||
|
expected.check_multi_interp_extensions = False
|
||||||
interpid, *_ = _interpreters.get_main()
|
interpid, *_ = _interpreters.get_main()
|
||||||
config = _interpreters.get_config(interpid)
|
config = _interpreters.get_config(interpid)
|
||||||
self.assert_ns_equal(config, expected)
|
self.assert_ns_equal(config, expected)
|
||||||
|
@ -2448,6 +2473,7 @@ class InterpreterConfigTests(unittest.TestCase):
|
||||||
'empty',
|
'empty',
|
||||||
use_main_obmalloc=True,
|
use_main_obmalloc=True,
|
||||||
gil='shared',
|
gil='shared',
|
||||||
|
check_multi_interp_extensions=bool(Py_GIL_DISABLED),
|
||||||
)
|
)
|
||||||
with new_interp(orig) as interpid:
|
with new_interp(orig) as interpid:
|
||||||
config = _interpreters.get_config(interpid)
|
config = _interpreters.get_config(interpid)
|
||||||
|
|
|
@ -30,7 +30,8 @@ import _imp
|
||||||
from test.support import os_helper
|
from test.support import os_helper
|
||||||
from test.support import (
|
from test.support import (
|
||||||
STDLIB_DIR, swap_attr, swap_item, cpython_only, is_apple_mobile, is_emscripten,
|
STDLIB_DIR, swap_attr, swap_item, cpython_only, is_apple_mobile, is_emscripten,
|
||||||
is_wasi, run_in_subinterp, run_in_subinterp_with_config, Py_TRACE_REFS)
|
is_wasi, run_in_subinterp, run_in_subinterp_with_config, Py_TRACE_REFS,
|
||||||
|
requires_gil_enabled, Py_GIL_DISABLED)
|
||||||
from test.support.import_helper import (
|
from test.support.import_helper import (
|
||||||
forget, make_legacy_pyc, unlink, unload, ready_to_import,
|
forget, make_legacy_pyc, unlink, unload, ready_to_import,
|
||||||
DirsOnSysPath, CleanImport, import_module)
|
DirsOnSysPath, CleanImport, import_module)
|
||||||
|
@ -158,6 +159,9 @@ def requires_singlephase_init(meth):
|
||||||
finally:
|
finally:
|
||||||
restore__testsinglephase()
|
restore__testsinglephase()
|
||||||
meth = cpython_only(meth)
|
meth = cpython_only(meth)
|
||||||
|
# gh-117649: free-threaded build does not currently support single-phase
|
||||||
|
# init modules in subinterpreters.
|
||||||
|
meth = requires_gil_enabled(meth)
|
||||||
return unittest.skipIf(_testsinglephase is None,
|
return unittest.skipIf(_testsinglephase is None,
|
||||||
'test requires _testsinglephase module')(meth)
|
'test requires _testsinglephase module')(meth)
|
||||||
|
|
||||||
|
@ -1876,8 +1880,9 @@ class SubinterpImportTests(unittest.TestCase):
|
||||||
# since they still don't implement multi-phase init.
|
# since they still don't implement multi-phase init.
|
||||||
module = '_imp'
|
module = '_imp'
|
||||||
require_builtin(module)
|
require_builtin(module)
|
||||||
with self.subTest(f'{module}: not strict'):
|
if not Py_GIL_DISABLED:
|
||||||
self.check_compatible_here(module, strict=False)
|
with self.subTest(f'{module}: not strict'):
|
||||||
|
self.check_compatible_here(module, strict=False)
|
||||||
with self.subTest(f'{module}: strict, not fresh'):
|
with self.subTest(f'{module}: strict, not fresh'):
|
||||||
self.check_compatible_here(module, strict=True)
|
self.check_compatible_here(module, strict=True)
|
||||||
|
|
||||||
|
@ -1888,8 +1893,9 @@ class SubinterpImportTests(unittest.TestCase):
|
||||||
require_frozen(module, skip=True)
|
require_frozen(module, skip=True)
|
||||||
if __import__(module).__spec__.origin != 'frozen':
|
if __import__(module).__spec__.origin != 'frozen':
|
||||||
raise unittest.SkipTest(f'{module} is unexpectedly not frozen')
|
raise unittest.SkipTest(f'{module} is unexpectedly not frozen')
|
||||||
with self.subTest(f'{module}: not strict'):
|
if not Py_GIL_DISABLED:
|
||||||
self.check_compatible_here(module, strict=False)
|
with self.subTest(f'{module}: not strict'):
|
||||||
|
self.check_compatible_here(module, strict=False)
|
||||||
with self.subTest(f'{module}: strict, not fresh'):
|
with self.subTest(f'{module}: strict, not fresh'):
|
||||||
self.check_compatible_here(module, strict=True)
|
self.check_compatible_here(module, strict=True)
|
||||||
|
|
||||||
|
@ -1908,8 +1914,9 @@ class SubinterpImportTests(unittest.TestCase):
|
||||||
def test_multi_init_extension_compat(self):
|
def test_multi_init_extension_compat(self):
|
||||||
module = '_testmultiphase'
|
module = '_testmultiphase'
|
||||||
require_extension(module)
|
require_extension(module)
|
||||||
with self.subTest(f'{module}: not strict'):
|
if not Py_GIL_DISABLED:
|
||||||
self.check_compatible_here(module, strict=False)
|
with self.subTest(f'{module}: not strict'):
|
||||||
|
self.check_compatible_here(module, strict=False)
|
||||||
with self.subTest(f'{module}: strict, not fresh'):
|
with self.subTest(f'{module}: strict, not fresh'):
|
||||||
self.check_compatible_here(module, strict=True)
|
self.check_compatible_here(module, strict=True)
|
||||||
with self.subTest(f'{module}: strict, fresh'):
|
with self.subTest(f'{module}: strict, fresh'):
|
||||||
|
@ -1930,8 +1937,9 @@ class SubinterpImportTests(unittest.TestCase):
|
||||||
self.check_incompatible_here(modname, filename, isolated=True)
|
self.check_incompatible_here(modname, filename, isolated=True)
|
||||||
with self.subTest(f'{modname}: not isolated'):
|
with self.subTest(f'{modname}: not isolated'):
|
||||||
self.check_incompatible_here(modname, filename, isolated=False)
|
self.check_incompatible_here(modname, filename, isolated=False)
|
||||||
with self.subTest(f'{modname}: not strict'):
|
if not Py_GIL_DISABLED:
|
||||||
self.check_compatible_here(modname, filename, strict=False)
|
with self.subTest(f'{modname}: not strict'):
|
||||||
|
self.check_compatible_here(modname, filename, strict=False)
|
||||||
|
|
||||||
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
||||||
def test_multi_init_extension_per_interpreter_gil_compat(self):
|
def test_multi_init_extension_per_interpreter_gil_compat(self):
|
||||||
|
@ -1949,16 +1957,18 @@ class SubinterpImportTests(unittest.TestCase):
|
||||||
with self.subTest(f'{modname}: not isolated, strict'):
|
with self.subTest(f'{modname}: not isolated, strict'):
|
||||||
self.check_compatible_here(modname, filename,
|
self.check_compatible_here(modname, filename,
|
||||||
strict=True, isolated=False)
|
strict=True, isolated=False)
|
||||||
with self.subTest(f'{modname}: not isolated, not strict'):
|
if not Py_GIL_DISABLED:
|
||||||
self.check_compatible_here(modname, filename,
|
with self.subTest(f'{modname}: not isolated, not strict'):
|
||||||
strict=False, isolated=False)
|
self.check_compatible_here(modname, filename,
|
||||||
|
strict=False, isolated=False)
|
||||||
|
|
||||||
@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
|
@unittest.skipIf(_testinternalcapi is None, "requires _testinternalcapi")
|
||||||
def test_python_compat(self):
|
def test_python_compat(self):
|
||||||
module = 'threading'
|
module = 'threading'
|
||||||
require_pure_python(module)
|
require_pure_python(module)
|
||||||
with self.subTest(f'{module}: not strict'):
|
if not Py_GIL_DISABLED:
|
||||||
self.check_compatible_here(module, strict=False)
|
with self.subTest(f'{module}: not strict'):
|
||||||
|
self.check_compatible_here(module, strict=False)
|
||||||
with self.subTest(f'{module}: strict, not fresh'):
|
with self.subTest(f'{module}: strict, not fresh'):
|
||||||
self.check_compatible_here(module, strict=True)
|
self.check_compatible_here(module, strict=True)
|
||||||
with self.subTest(f'{module}: strict, fresh'):
|
with self.subTest(f'{module}: strict, fresh'):
|
||||||
|
|
|
@ -682,6 +682,9 @@ class IncompatibleExtensionModuleRestrictionsTests(unittest.TestCase):
|
||||||
raise ImportError(excsnap.msg)
|
raise ImportError(excsnap.msg)
|
||||||
|
|
||||||
@unittest.skipIf(_testsinglephase is None, "test requires _testsinglephase module")
|
@unittest.skipIf(_testsinglephase is None, "test requires _testsinglephase module")
|
||||||
|
# gh-117649: single-phase init modules are not currently supported in
|
||||||
|
# subinterpreters in the free-threaded build
|
||||||
|
@support.expected_failure_if_gil_disabled()
|
||||||
def test_single_phase_init_module(self):
|
def test_single_phase_init_module(self):
|
||||||
script = textwrap.dedent('''
|
script = textwrap.dedent('''
|
||||||
from importlib.util import _incompatible_extension_module_restrictions
|
from importlib.util import _incompatible_extension_module_restrictions
|
||||||
|
@ -706,6 +709,7 @@ class IncompatibleExtensionModuleRestrictionsTests(unittest.TestCase):
|
||||||
self.run_with_own_gil(script)
|
self.run_with_own_gil(script)
|
||||||
|
|
||||||
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
|
||||||
|
@support.requires_gil_enabled("gh-117649: not supported in free-threaded build")
|
||||||
def test_incomplete_multi_phase_init_module(self):
|
def test_incomplete_multi_phase_init_module(self):
|
||||||
# Apple extensions must be distributed as frameworks. This requires
|
# Apple extensions must be distributed as frameworks. This requires
|
||||||
# a specialist loader.
|
# a specialist loader.
|
||||||
|
|
|
@ -10,6 +10,7 @@ from test import support
|
||||||
from test.support import import_helper
|
from test.support import import_helper
|
||||||
# Raise SkipTest if subinterpreters not supported.
|
# Raise SkipTest if subinterpreters not supported.
|
||||||
_interpreters = import_helper.import_module('_xxsubinterpreters')
|
_interpreters = import_helper.import_module('_xxsubinterpreters')
|
||||||
|
from test.support import Py_GIL_DISABLED
|
||||||
from test.support import interpreters
|
from test.support import interpreters
|
||||||
from test.support.interpreters import (
|
from test.support.interpreters import (
|
||||||
InterpreterError, InterpreterNotFoundError, ExecutionFailed,
|
InterpreterError, InterpreterNotFoundError, ExecutionFailed,
|
||||||
|
@ -1162,7 +1163,7 @@ class LowLevelTests(TestBase):
|
||||||
allow_exec=True,
|
allow_exec=True,
|
||||||
allow_threads=True,
|
allow_threads=True,
|
||||||
allow_daemon_threads=True,
|
allow_daemon_threads=True,
|
||||||
check_multi_interp_extensions=False,
|
check_multi_interp_extensions=bool(Py_GIL_DISABLED),
|
||||||
gil='shared',
|
gil='shared',
|
||||||
),
|
),
|
||||||
'empty': types.SimpleNamespace(
|
'empty': types.SimpleNamespace(
|
||||||
|
@ -1361,6 +1362,7 @@ class LowLevelTests(TestBase):
|
||||||
with self.subTest('custom'):
|
with self.subTest('custom'):
|
||||||
orig = _interpreters.new_config('empty')
|
orig = _interpreters.new_config('empty')
|
||||||
orig.use_main_obmalloc = True
|
orig.use_main_obmalloc = True
|
||||||
|
orig.check_multi_interp_extensions = bool(Py_GIL_DISABLED)
|
||||||
orig.gil = 'shared'
|
orig.gil = 'shared'
|
||||||
interpid = _interpreters.create(orig)
|
interpid = _interpreters.create(orig)
|
||||||
config = _interpreters.get_config(interpid)
|
config = _interpreters.get_config(interpid)
|
||||||
|
@ -1410,13 +1412,8 @@ class LowLevelTests(TestBase):
|
||||||
with self.subTest('main'):
|
with self.subTest('main'):
|
||||||
expected = _interpreters.new_config('legacy')
|
expected = _interpreters.new_config('legacy')
|
||||||
expected.gil = 'own'
|
expected.gil = 'own'
|
||||||
interpid, *_ = _interpreters.get_main()
|
if Py_GIL_DISABLED:
|
||||||
config = _interpreters.get_config(interpid)
|
expected.check_multi_interp_extensions = False
|
||||||
self.assert_ns_equal(config, expected)
|
|
||||||
|
|
||||||
with self.subTest('main'):
|
|
||||||
expected = _interpreters.new_config('legacy')
|
|
||||||
expected.gil = 'own'
|
|
||||||
interpid, *_ = _interpreters.get_main()
|
interpid, *_ = _interpreters.get_main()
|
||||||
config = _interpreters.get_config(interpid)
|
config = _interpreters.get_config(interpid)
|
||||||
self.assert_ns_equal(config, expected)
|
self.assert_ns_equal(config, expected)
|
||||||
|
|
|
@ -1527,6 +1527,7 @@ class SubinterpThreadingTests(BaseTestCase):
|
||||||
{before_start}
|
{before_start}
|
||||||
t.start()
|
t.start()
|
||||||
""")
|
""")
|
||||||
|
check_multi_interp_extensions = bool(support.Py_GIL_DISABLED)
|
||||||
script = textwrap.dedent(f"""
|
script = textwrap.dedent(f"""
|
||||||
import test.support
|
import test.support
|
||||||
test.support.run_in_subinterp_with_config(
|
test.support.run_in_subinterp_with_config(
|
||||||
|
@ -1536,7 +1537,7 @@ class SubinterpThreadingTests(BaseTestCase):
|
||||||
allow_exec=True,
|
allow_exec=True,
|
||||||
allow_threads={allowed},
|
allow_threads={allowed},
|
||||||
allow_daemon_threads={daemon_allowed},
|
allow_daemon_threads={daemon_allowed},
|
||||||
check_multi_interp_extensions=False,
|
check_multi_interp_extensions={check_multi_interp_extensions},
|
||||||
own_gil=False,
|
own_gil=False,
|
||||||
)
|
)
|
||||||
""")
|
""")
|
||||||
|
|
|
@ -3696,9 +3696,16 @@ _imp__override_multi_interp_extensions_check_impl(PyObject *module,
|
||||||
"cannot be used in the main interpreter");
|
"cannot be used in the main interpreter");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
PyErr_SetString(PyExc_RuntimeError,
|
||||||
|
"_imp._override_multi_interp_extensions_check() "
|
||||||
|
"cannot be used in the free-threaded build");
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
int oldvalue = OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp);
|
int oldvalue = OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp);
|
||||||
OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp) = override;
|
OVERRIDE_MULTI_INTERP_EXTENSIONS_CHECK(interp) = override;
|
||||||
return PyLong_FromLong(oldvalue);
|
return PyLong_FromLong(oldvalue);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DYNAMIC_LOADING
|
#ifdef HAVE_DYNAMIC_LOADING
|
||||||
|
|
|
@ -559,6 +559,15 @@ init_interp_settings(PyInterpreterState *interp,
|
||||||
return _PyStatus_ERR("per-interpreter obmalloc does not support "
|
return _PyStatus_ERR("per-interpreter obmalloc does not support "
|
||||||
"single-phase init extension modules");
|
"single-phase init extension modules");
|
||||||
}
|
}
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
if (!_Py_IsMainInterpreter(interp) &&
|
||||||
|
!config->check_multi_interp_extensions)
|
||||||
|
{
|
||||||
|
return _PyStatus_ERR("The free-threaded build does not support "
|
||||||
|
"single-phase init extension modules in "
|
||||||
|
"subinterpreters");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (config->allow_fork) {
|
if (config->allow_fork) {
|
||||||
interp->feature_flags |= Py_RTFLAGS_FORK;
|
interp->feature_flags |= Py_RTFLAGS_FORK;
|
||||||
|
@ -647,8 +656,10 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
|
||||||
}
|
}
|
||||||
|
|
||||||
PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
|
PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
|
||||||
// The main interpreter always has its own GIL.
|
// The main interpreter always has its own GIL and supports single-phase
|
||||||
|
// init extensions.
|
||||||
config.gil = PyInterpreterConfig_OWN_GIL;
|
config.gil = PyInterpreterConfig_OWN_GIL;
|
||||||
|
config.check_multi_interp_extensions = 0;
|
||||||
status = init_interp_settings(interp, &config);
|
status = init_interp_settings(interp, &config);
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
return status;
|
return status;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue