Skip to content

Commit 135abec

Browse files
committed
Fix interpreter lifecycle cleanup paths
Fix multiple resource-management and error-path bugs in the interpreter lifecycle. Release the builtins module reference on builtin initialization failures and keep it owned until default import initialization succeeds, avoiding an extra NULL assignment. Also DECREF results from non-dict sys.modules clear calls, route subinterpreter initialization failures through cleanup after thread-state detach, release __main__ setup references on PyDict_SetItemString failures, and check stdin/stdout sys object setup failures consistently with stderr. Tests run: - ./configure --with-pydebug - git diff --check - make -j2 Python/pylifecycle.o - make -j2 python Programs/_testembed - make -j2 - Programs/_testembed test_repeated_init_and_subinterpreters - ./python - <<'PY' import _interpreters interp = _interpreters.create() _interpreters.destroy(interp) print('ok') PY - make patchcheck (fails because this checkout has no upstream remote matching https://github.com/python/cpython)
1 parent cc5cf14 commit 135abec

1 file changed

Lines changed: 28 additions & 8 deletions

File tree

Python/pylifecycle.c

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -909,23 +909,25 @@ pycore_init_builtins(PyThreadState *tstate)
909909
interp->callable_cache.object__getattribute__ = object__getattribute__;
910910

911911
if (_PyType_InitSlotDefs(interp) < 0) {
912+
Py_DECREF(bimod);
912913
return _PyStatus_ERR("failed to init slotdefs");
913914
}
914915

915916
if (_PyBuiltins_AddExceptions(bimod) < 0) {
917+
Py_DECREF(bimod);
916918
return _PyStatus_ERR("failed to add exceptions to builtins");
917919
}
918920

919921
interp->builtins_copy = PyDict_Copy(interp->builtins);
920922
if (interp->builtins_copy == NULL) {
921923
goto error;
922924
}
923-
Py_DECREF(bimod);
924925

925926
if (_PyImport_InitDefaultImportFunc(interp) < 0) {
926927
goto error;
927928
}
928929

930+
Py_DECREF(bimod);
929931
assert(!_PyErr_Occurred(tstate));
930932
return _PyStatus_OK();
931933

@@ -1823,9 +1825,13 @@ finalize_clear_modules_dict(PyObject *modules)
18231825
PyDict_Clear(modules);
18241826
}
18251827
else {
1826-
if (PyObject_CallMethodNoArgs(modules, &_Py_ID(clear)) == NULL) {
1828+
PyObject *result = PyObject_CallMethodNoArgs(modules, &_Py_ID(clear));
1829+
if (result == NULL) {
18271830
PyErr_FormatUnraisable("Exception ignored while clearing sys.modules");
18281831
}
1832+
else {
1833+
Py_DECREF(result);
1834+
}
18291835
}
18301836
}
18311837

@@ -2702,14 +2708,14 @@ new_interpreter(PyThreadState **tstate_p,
27022708
// didn't depend on interp->feature_flags being set already.
27032709
status = _PyObject_InitState(interp);
27042710
if (_PyStatus_EXCEPTION(status)) {
2705-
return status;
2711+
goto error;
27062712
}
27072713

27082714
#ifdef Py_STATS
27092715
// initialize pystats. This must be done after the settings are loaded.
27102716
status = _PyStats_InterpInit(interp);
27112717
if (_PyStatus_EXCEPTION(status)) {
2712-
return status;
2718+
goto error;
27132719
}
27142720
#endif
27152721

@@ -2929,6 +2935,7 @@ add_main_module(PyInterpreterState *interp)
29292935
return _PyStatus_ERR("Failed to retrieve builtins module");
29302936
}
29312937
if (PyDict_SetItemString(d, "__builtins__", bimod) < 0) {
2938+
Py_DECREF(bimod);
29322939
return _PyStatus_ERR("Failed to initialize __main__.__builtins__");
29332940
}
29342941
Py_DECREF(bimod);
@@ -2952,6 +2959,7 @@ add_main_module(PyInterpreterState *interp)
29522959
return _PyStatus_ERR("Failed to retrieve BuiltinImporter");
29532960
}
29542961
if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
2962+
Py_DECREF(loader);
29552963
return _PyStatus_ERR("Failed to initialize __main__.__loader__");
29562964
}
29572965
Py_DECREF(loader);
@@ -3186,8 +3194,14 @@ init_sys_streams(PyThreadState *tstate)
31863194
config->stdio_errors);
31873195
if (std == NULL)
31883196
goto error;
3189-
PySys_SetObject("__stdin__", std);
3190-
_PySys_SetAttr(&_Py_ID(stdin), std);
3197+
if (PySys_SetObject("__stdin__", std) < 0) {
3198+
Py_DECREF(std);
3199+
goto error;
3200+
}
3201+
if (_PySys_SetAttr(&_Py_ID(stdin), std) < 0) {
3202+
Py_DECREF(std);
3203+
goto error;
3204+
}
31913205
Py_DECREF(std);
31923206

31933207
/* Set sys.stdout */
@@ -3197,8 +3211,14 @@ init_sys_streams(PyThreadState *tstate)
31973211
config->stdio_errors);
31983212
if (std == NULL)
31993213
goto error;
3200-
PySys_SetObject("__stdout__", std);
3201-
_PySys_SetAttr(&_Py_ID(stdout), std);
3214+
if (PySys_SetObject("__stdout__", std) < 0) {
3215+
Py_DECREF(std);
3216+
goto error;
3217+
}
3218+
if (_PySys_SetAttr(&_Py_ID(stdout), std) < 0) {
3219+
Py_DECREF(std);
3220+
goto error;
3221+
}
32023222
Py_DECREF(std);
32033223

32043224
#if 1 /* Disable this if you have trouble debugging bootstrap stuff */

0 commit comments

Comments
 (0)