|
45 | 45 | Py_GIL_DISABLED, |
46 | 46 | no_rerun, |
47 | 47 | force_not_colorized_test_class, |
| 48 | + catch_unraisable_exception |
48 | 49 | ) |
49 | 50 | from test.support.import_helper import ( |
50 | 51 | forget, make_legacy_pyc, unlink, unload, ready_to_import, |
@@ -2517,6 +2518,32 @@ def test_disallowed_reimport(self): |
2517 | 2518 | excsnap = _interpreters.run_string(interpid, script) |
2518 | 2519 | self.assertIsNot(excsnap, None) |
2519 | 2520 |
|
| 2521 | + @requires_subinterpreters |
| 2522 | + def test_pyinit_function_raises_exception(self): |
| 2523 | + # gh-144601: PyInit functions that raised exceptions would cause a |
| 2524 | + # crash when imported from a subinterpreter. |
| 2525 | + import _testsinglephase |
| 2526 | + filename = _testsinglephase.__file__ |
| 2527 | + script = f"""if True: |
| 2528 | + from test.test_import import import_extension_from_file |
| 2529 | +
|
| 2530 | + import_extension_from_file('_testsinglephase_raise_exception', {filename!r})""" |
| 2531 | + |
| 2532 | + interp = _interpreters.create() |
| 2533 | + try: |
| 2534 | + with catch_unraisable_exception() as cm: |
| 2535 | + exception = _interpreters.run_string(interp, script) |
| 2536 | + unraisable = cm.unraisable |
| 2537 | + finally: |
| 2538 | + _interpreters.destroy(interp) |
| 2539 | + |
| 2540 | + self.assertIsNotNone(exception) |
| 2541 | + self.assertIsNotNone(exception.type.__name__, "ImportError") |
| 2542 | + self.assertIsNotNone(exception.msg, "failed to import from subinterpreter due to exception") |
| 2543 | + self.assertIsNotNone(unraisable) |
| 2544 | + self.assertIs(unraisable.exc_type, RuntimeError) |
| 2545 | + self.assertEqual(str(unraisable.exc_value), "evil") |
| 2546 | + |
2520 | 2547 |
|
2521 | 2548 | class TestSinglePhaseSnapshot(ModuleSnapshot): |
2522 | 2549 | """A representation of a single-phase init module for testing. |
|
0 commit comments