bpo-28411: Isolate PyInterpreterState.modules (#3575)
A bunch of code currently uses PyInterpreterState.modules directly instead of PyImport_GetModuleDict(). This complicates efforts to make changes relative to sys.modules. This patch switches to using PyImport_GetModuleDict() uniformly. Also, a number of related uses of sys.modules are updated for uniformity for the same reason.
Note that this code was already reviewed and merged as part of #1638. I reverted that and am now splitting it up into more focused parts.
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 2aac901..5c8cf5b 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -675,9 +675,20 @@
if (!_PyFloat_Init())
Py_FatalError("Py_InitializeCore: can't init float");
- interp->modules = PyDict_New();
- if (interp->modules == NULL)
+ PyObject *modules = PyDict_New();
+ if (modules == NULL)
Py_FatalError("Py_InitializeCore: can't make modules dictionary");
+ interp->modules = modules;
+
+ sysmod = _PySys_BeginInit();
+ if (sysmod == NULL)
+ Py_FatalError("Py_InitializeCore: can't initialize sys");
+ interp->sysdict = PyModule_GetDict(sysmod);
+ if (interp->sysdict == NULL)
+ Py_FatalError("Py_InitializeCore: can't initialize sys dict");
+ Py_INCREF(interp->sysdict);
+ PyDict_SetItemString(interp->sysdict, "modules", modules);
+ _PyImport_FixupBuiltin(sysmod, "sys", modules);
/* Init Unicode implementation; relies on the codec registry */
if (_PyUnicode_Init() < 0)
@@ -689,7 +700,7 @@
bimod = _PyBuiltin_Init();
if (bimod == NULL)
Py_FatalError("Py_InitializeCore: can't initialize builtins modules");
- _PyImport_FixupBuiltin(bimod, "builtins");
+ _PyImport_FixupBuiltin(bimod, "builtins", modules);
interp->builtins = PyModule_GetDict(bimod);
if (interp->builtins == NULL)
Py_FatalError("Py_InitializeCore: can't initialize builtins dict");
@@ -698,17 +709,6 @@
/* initialize builtin exceptions */
_PyExc_Init(bimod);
- sysmod = _PySys_BeginInit();
- if (sysmod == NULL)
- Py_FatalError("Py_InitializeCore: can't initialize sys");
- interp->sysdict = PyModule_GetDict(sysmod);
- if (interp->sysdict == NULL)
- Py_FatalError("Py_InitializeCore: can't initialize sys dict");
- Py_INCREF(interp->sysdict);
- _PyImport_FixupBuiltin(sysmod, "sys");
- PyDict_SetItemString(interp->sysdict, "modules",
- interp->modules);
-
/* Set up a preliminary stderr printer until we have enough
infrastructure for the io module in place. */
pstderr = PyFile_NewStdPrinter(fileno(stderr));
@@ -1211,9 +1211,23 @@
/* XXX The following is lax in error checking */
- interp->modules = PyDict_New();
+ PyObject *modules = PyDict_New();
+ if (modules == NULL)
+ Py_FatalError("Py_NewInterpreter: can't make modules dictionary");
+ interp->modules = modules;
- bimod = _PyImport_FindBuiltin("builtins");
+ sysmod = _PyImport_FindBuiltin("sys", modules);
+ if (sysmod != NULL) {
+ interp->sysdict = PyModule_GetDict(sysmod);
+ if (interp->sysdict == NULL)
+ goto handle_error;
+ Py_INCREF(interp->sysdict);
+ PyDict_SetItemString(interp->sysdict, "modules", modules);
+ PySys_SetPath(Py_GetPath());
+ _PySys_EndInit(interp->sysdict);
+ }
+
+ bimod = _PyImport_FindBuiltin("builtins", modules);
if (bimod != NULL) {
interp->builtins = PyModule_GetDict(bimod);
if (interp->builtins == NULL)
@@ -1224,18 +1238,9 @@
/* initialize builtin exceptions */
_PyExc_Init(bimod);
- sysmod = _PyImport_FindBuiltin("sys");
if (bimod != NULL && sysmod != NULL) {
PyObject *pstderr;
- interp->sysdict = PyModule_GetDict(sysmod);
- if (interp->sysdict == NULL)
- goto handle_error;
- Py_INCREF(interp->sysdict);
- _PySys_EndInit(interp->sysdict);
- PySys_SetPath(Py_GetPath());
- PyDict_SetItemString(interp->sysdict, "modules",
- interp->modules);
/* Set up a preliminary stderr printer until we have enough
infrastructure for the io module in place. */
pstderr = PyFile_NewStdPrinter(fileno(stderr));
@@ -1911,9 +1916,8 @@
{
_Py_IDENTIFIER(_shutdown);
PyObject *result;
- PyThreadState *tstate = PyThreadState_GET();
- PyObject *threading = PyMapping_GetItemString(tstate->interp->modules,
- "threading");
+ PyObject *modules = PyImport_GetModuleDict();
+ PyObject *threading = PyMapping_GetItemString(modules, "threading");
if (threading == NULL) {
/* threading not imported */
PyErr_Clear();