Skip to content

Commit 8a8a344

Browse files
committed
Test that Py_MOD_GIL_USED re-enables the GIL
1 parent 60a669c commit 8a8a344

2 files changed

Lines changed: 84 additions & 0 deletions

File tree

Lib/test/test_import/__init__.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import builtins
2+
import concurrent.interpreters
23
import errno
34
import glob
45
import json
@@ -3407,6 +3408,35 @@ def test_from_modexport(self):
34073408

34083409
self.assertEqual(module.__name__, modname)
34093410

3411+
def test_from_modexport_gil_used(self):
3412+
# Test that a module with Py_MOD_GIL_USED (re-)enables the GIL.
3413+
# Do this in a new interpreter to avoid interfering with global state.
3414+
modname = '_test_from_modexport_gil_used'
3415+
filename = _testmultiphase.__file__
3416+
interp = concurrent.interpreters.create()
3417+
self.addCleanup(interp.close)
3418+
queue = concurrent.interpreters.create_queue()
3419+
interp.prepare_main(
3420+
modname=modname,
3421+
filename=filename,
3422+
queue=queue,
3423+
)
3424+
enabled_before = sys._is_gil_enabled()
3425+
interp.exec(f"""if True:
3426+
import sys
3427+
from {__name__} import import_extension_from_file
3428+
module = import_extension_from_file(modname, filename,
3429+
put_in_sys_modules=False)
3430+
queue.put(module.__name__)
3431+
queue.put(sys._is_gil_enabled())
3432+
""")
3433+
3434+
self.assertEqual(queue.get(), modname)
3435+
self.assertEqual(queue.get(), True)
3436+
self.assertTrue(queue.empty())
3437+
3438+
self.assertEqual(enabled_before, sys._is_gil_enabled())
3439+
34103440
def test_from_modexport_null(self):
34113441
modname = '_test_from_modexport_null'
34123442
filename = _testmultiphase.__file__
@@ -3428,6 +3458,35 @@ def test_from_modexport_create_nonmodule(self):
34283458
put_in_sys_modules=False)
34293459
self.assertIsInstance(module, str)
34303460

3461+
def test_from_modexport_create_nonmodule_gil_used(self):
3462+
# Test that a module with Py_MOD_GIL_USED (re-)enables the GIL.
3463+
# Do this in a new interpreter to avoid interfering with global state.
3464+
modname = '_test_from_modexport_create_nonmodule_gil_used'
3465+
filename = _testmultiphase.__file__
3466+
interp = concurrent.interpreters.create()
3467+
self.addCleanup(interp.close)
3468+
queue = concurrent.interpreters.create_queue()
3469+
interp.prepare_main(
3470+
modname=modname,
3471+
filename=filename,
3472+
queue=queue,
3473+
)
3474+
enabled_before = sys._is_gil_enabled()
3475+
interp.exec(f"""if True:
3476+
import sys
3477+
from {__name__} import import_extension_from_file
3478+
module = import_extension_from_file(modname, filename,
3479+
put_in_sys_modules=False)
3480+
queue.put(module)
3481+
queue.put(sys._is_gil_enabled())
3482+
""")
3483+
3484+
self.assertIsInstance(queue.get(), str)
3485+
self.assertEqual(queue.get(), True)
3486+
self.assertTrue(queue.empty())
3487+
3488+
self.assertEqual(enabled_before, sys._is_gil_enabled())
3489+
34313490
def test_from_modexport_smoke(self):
34323491
# General positive test for sundry features
34333492
# (PyModule_FromSlotsAndSpec tests exercise these more carefully)

Modules/_testmultiphase.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,18 @@ PyModExport__test_from_modexport(void)
10311031
return slots;
10321032
}
10331033

1034+
PyMODEXPORT_FUNC
1035+
PyModExport__test_from_modexport_gil_used(void)
1036+
{
1037+
static PyModuleDef_Slot slots[] = {
1038+
{Py_mod_name, "_test_from_modexport_gil_used"},
1039+
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
1040+
{Py_mod_gil, Py_MOD_GIL_USED},
1041+
{0},
1042+
};
1043+
return slots;
1044+
}
1045+
10341046
PyMODEXPORT_FUNC
10351047
PyModExport__test_from_modexport_null(void)
10361048
{
@@ -1082,6 +1094,19 @@ PyModExport__test_from_modexport_create_nonmodule(void)
10821094
return slots;
10831095
}
10841096

1097+
PyMODEXPORT_FUNC
1098+
PyModExport__test_from_modexport_create_nonmodule_gil_used(void)
1099+
{
1100+
static PyModuleDef_Slot slots[] = {
1101+
{Py_mod_name, "_test_from_modexport_create_nonmodule"},
1102+
{Py_mod_create, modexport_create_string},
1103+
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
1104+
{Py_mod_gil, Py_MOD_GIL_USED},
1105+
{0},
1106+
};
1107+
return slots;
1108+
}
1109+
10851110
static PyModuleDef_Slot modexport_empty_slots[] = {
10861111
{0},
10871112
};

0 commit comments

Comments
 (0)