Skip to content

Commit

Permalink
pythongh-117649: Raise ImportError for unsupported modules in free-th…
Browse files Browse the repository at this point in the history
…readed build

The free-threaded build does not currently support the combination of
single-phase init modules and legacy, non-isolated subinterpreters. Note
that with isolated interpreters, single-phase init modules already
trigger `ImportError`.
  • Loading branch information
colesbury committed Apr 8, 2024
1 parent 24a2bd0 commit e273d24
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 5 deletions.
3 changes: 3 additions & 0 deletions Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from test.support import threading_helper
from test.support import warnings_helper
from test.support import requires_limited_api
from test.support import requires_gil_enabled
from test.support.script_helper import assert_python_failure, assert_python_ok, run_python_until_end
try:
import _posixsubprocess
Expand Down Expand Up @@ -2070,6 +2071,7 @@ def test_configured_settings(self):

@unittest.skipIf(_testsinglephase is None, "test requires _testsinglephase module")
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
@requires_gil_enabled("gh-117649: test does not work in free-threaded build")
def test_overridden_setting_extensions_subinterp_check(self):
"""
PyInterpreterConfig.check_multi_interp_extensions can be overridden
Expand Down Expand Up @@ -2165,6 +2167,7 @@ def test_mutate_exception(self):
self.assertFalse(hasattr(binascii.Error, "foobar"))

@unittest.skipIf(_testmultiphase is None, "test requires _testmultiphase module")
@requires_gil_enabled("gh-117649: test does not work in free-threaded build")
def test_module_state_shared_in_global(self):
"""
bpo-44050: Extension module state should be shared between interpreters
Expand Down
6 changes: 5 additions & 1 deletion Lib/test/test_import/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
from test.support import os_helper
from test.support import (
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)
from test.support.import_helper import (
forget, make_legacy_pyc, unlink, unload, ready_to_import,
DirsOnSysPath, CleanImport, import_module)
Expand Down Expand Up @@ -158,6 +159,9 @@ def meth(self, _meth=meth):
finally:
restore__testsinglephase()
meth = cpython_only(meth)
# gh-117649: free-threaded build does not currently support legacy
# single-phase init modules in subinterpreters.
meth = requires_gil_enabled(meth)
return unittest.skipIf(_testsinglephase is None,
'test requires _testsinglephase module')(meth)

Expand Down
19 changes: 15 additions & 4 deletions Lib/test/test_importlib/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import re
import string
import sys
import sysconfig
from test import support
import textwrap
import types
Expand Down Expand Up @@ -688,10 +689,20 @@ def test_single_phase_init_module(self):
with _incompatible_extension_module_restrictions(disable_check=True):
import _testsinglephase
''')
with self.subTest('check disabled, shared GIL'):
self.run_with_shared_gil(script)
with self.subTest('check disabled, per-interpreter GIL'):
self.run_with_own_gil(script)
if not sysconfig.get_config_var('Py_GIL_DISABLED'):
with self.subTest('check disabled, shared GIL'):
self.run_with_shared_gil(script)
with self.subTest('check disabled, per-interpreter GIL'):
self.run_with_own_gil(script)
else:
# gh-117649: Py_GIL_DISABLED builds do not support legacy
# single-phase init extensions within subinterpreters.
with self.subTest('check disabled, shared GIL'):
with self.assertRaises(ImportError):
self.run_with_shared_gil(script)
with self.subTest('check disabled, per-interpreter GIL'):
with self.assertRaises(ImportError):
self.run_with_own_gil(script)

script = textwrap.dedent(f'''
from importlib.util import _incompatible_extension_module_restrictions
Expand Down
13 changes: 13 additions & 0 deletions Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -1244,6 +1244,19 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
return NULL;
}

/* The free-threaded build does not currently support single-phase init
extensions in subinterpreters because they break isolation. */
#ifdef Py_GIL_DISABLED
if (def->m_size == -1 && !_Py_IsMainInterpreter(tstate->interp)) {
return PyErr_Format(
PyExc_ImportError,
"module %s does not support the combination of free-threading "
"and subinterpreters",
name_buf);
return NULL;
}
#endif

PyObject *mod, *mdict;
PyObject *modules = MODULES(tstate->interp);

Expand Down

0 comments on commit e273d24

Please sign in to comment.