mirror of
https://github.com/python/cpython.git
synced 2025-08-04 08:59:19 +00:00
bpo-38076 Clear the interpreter state only after clearing module globals (GH-18039)
Currently, during runtime destruction, `_PyImport_Cleanup` is clearing the interpreter state before clearing out the modules themselves. This leads to a segfault on modules that rely on the module state to clear themselves up. For example, let's take the small snippet added in the issue by @DinoV : ``` import _struct class C: def __init__(self): self.pack = _struct.pack def __del__(self): self.pack('I', -42) _struct.x = C() ``` The module `_struct` uses the module state to run `pack`. Therefore, the module state has to be alive until after the module has been cleared out to successfully run `C.__del__`. This happens at line 606, when `_PyImport_Cleanup` calls `_PyModule_Clear`. In fact, the loop that calls `_PyModule_Clear` has in its comments: > Now, if there are any modules left alive, clear their globals to minimize potential leaks. All C extension modules actually end up here, since they are kept alive in the interpreter state. That means that we can't clear the module state (which is used by C Extensions) before we run that loop. Moving `_PyInterpreterState_ClearModules` until after it, fixes the segfault in the code snippet. Finally, this updates a test in `io` to correctly assert the error that it now throws (since it now finds the io module state). The test that uses this is: `test_create_at_shutdown_without_encoding`. Given this test is now working is a proof that the module state now stays alive even when `__del__` is called at module destruction time. Thus, I didn't add a new tests for this. https://bugs.python.org/issue38076
This commit is contained in:
parent
b6999e5690
commit
4590f72259
5 changed files with 41 additions and 3 deletions
|
@ -3683,7 +3683,7 @@ def _to_memoryview(buf):
|
|||
|
||||
class CTextIOWrapperTest(TextIOWrapperTest):
|
||||
io = io
|
||||
shutdown_error = "RuntimeError: could not find io module state"
|
||||
shutdown_error = "LookupError: unknown encoding: ascii"
|
||||
|
||||
def test_initialization(self):
|
||||
r = self.BytesIO(b"\xc3\xa9\n\n")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue