Skip to content

Commit e38f141

Browse files
Fix destroying a not-ready interpreter.
1 parent 4f92794 commit e38f141

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

Lib/test/test_interpreters/test_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1494,7 +1494,7 @@ def test_whence(self):
14941494
self.assertEqual(whence, _interpreters.WHENCE_STDLIB)
14951495

14961496
for orig, name in {
1497-
# XXX Also check WHENCE_UNKNOWN.
1497+
_interpreters.WHENCE_UNKNOWN: 'not ready',
14981498
_interpreters.WHENCE_LEGACY_CAPI: 'legacy C-API',
14991499
_interpreters.WHENCE_CAPI: 'C-API',
15001500
_interpreters.WHENCE_XI: 'cross-interpreter C-API',

Python/crossinterp.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,20 @@ void
18721872
_PyXI_EndInterpreter(PyInterpreterState *interp,
18731873
PyThreadState *tstate, PyThreadState **p_save_tstate)
18741874
{
1875+
long whence = _PyInterpreterState_GetWhence(interp);
1876+
assert(whence != _PyInterpreterState_WHENCE_RUNTIME);
1877+
1878+
if (!_PyInterpreterState_IsReady(interp)) {
1879+
assert(whence == _PyInterpreterState_WHENCE_UNKNOWN);
1880+
// PyInterpreterState_Clear() requires the GIL,
1881+
// which a not-ready does not have, so we don't clear it.
1882+
// That means there may be leaks here until clearing the
1883+
// interpreter is fixed.
1884+
PyInterpreterState_Delete(interp);
1885+
return;
1886+
}
1887+
assert(whence != _PyInterpreterState_WHENCE_UNKNOWN);
1888+
18751889
PyThreadState *save_tstate = NULL;
18761890
PyThreadState *cur_tstate = PyThreadState_GET();
18771891
if (tstate == NULL) {
@@ -1893,18 +1907,7 @@ _PyXI_EndInterpreter(PyInterpreterState *interp,
18931907
}
18941908
}
18951909

1896-
long whence = _PyInterpreterState_GetWhence(interp);
1897-
assert(whence != _PyInterpreterState_WHENCE_RUNTIME);
1898-
if (whence == _PyInterpreterState_WHENCE_UNKNOWN) {
1899-
assert(!_PyInterpreterState_IsReady(interp));
1900-
PyThreadState *tstate = PyThreadState_New(interp);
1901-
save_tstate = PyThreadState_Swap(tstate);
1902-
_PyInterpreterState_Clear(tstate);
1903-
PyInterpreterState_Delete(interp);
1904-
}
1905-
else {
1906-
Py_EndInterpreter(tstate);
1907-
}
1910+
Py_EndInterpreter(tstate);
19081911

19091912
if (p_save_tstate != NULL) {
19101913
save_tstate = *p_save_tstate;

0 commit comments

Comments
 (0)