bpo-42260: Initialize time and warnings earlier at startup (GH-23249)

* Call _PyTime_Init() and _PyWarnings_InitState() earlier during the
  Python initialization.
* Inline _PyImportHooks_Init() into _PySys_InitCore().
* The _warnings initialization function no longer call
  _PyWarnings_InitState() to prevent resetting filters_version to 0.
* _PyWarnings_InitState() now returns an int and no longer clear the
  state in case of error (it's done anyway at Python exit).
* Rework init_importlib(), fix refleaks on errors.
This commit is contained in:
Victor Stinner 2020-11-12 15:14:13 +01:00 committed by GitHub
parent d19fa7a337
commit ef75a625cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 133 deletions

View File

@ -190,10 +190,14 @@ struct _is {
struct _ceval_state ceval; struct _ceval_state ceval;
struct _gc_runtime_state gc; struct _gc_runtime_state gc;
// sys.modules dictionary
PyObject *modules; PyObject *modules;
PyObject *modules_by_index; PyObject *modules_by_index;
// Dictionary of the sys module
PyObject *sysdict; PyObject *sysdict;
// Dictionary of the builtins module
PyObject *builtins; PyObject *builtins;
// importlib module
PyObject *importlib; PyObject *importlib;
/* Used in Modules/_threadmodule.c. */ /* Used in Modules/_threadmodule.c. */
@ -218,7 +222,7 @@ struct _is {
PyObject *builtins_copy; PyObject *builtins_copy;
PyObject *import_func; PyObject *import_func;
/* Initialized to PyEval_EvalFrameDefault(). */ // Initialized to _PyEval_EvalFrameDefault().
_PyFrameEvalFunction eval_frame; _PyFrameEvalFunction eval_frame;
Py_ssize_t co_extra_user_count; Py_ssize_t co_extra_user_count;

View File

@ -48,7 +48,6 @@ extern int _PySys_UpdateConfig(PyThreadState *tstate);
extern PyStatus _PyExc_Init(PyThreadState *tstate); extern PyStatus _PyExc_Init(PyThreadState *tstate);
extern PyStatus _PyErr_Init(void); extern PyStatus _PyErr_Init(void);
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod); extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
extern PyStatus _PyImportHooks_Init(PyThreadState *tstate);
extern int _PyFloat_Init(void); extern int _PyFloat_Init(void);
extern PyStatus _Py_HashRandomization_Init(const PyConfig *); extern PyStatus _Py_HashRandomization_Init(const PyConfig *);

View File

@ -17,7 +17,7 @@ struct _warnings_runtime_state {
long filters_version; long filters_version;
}; };
extern PyStatus _PyWarnings_InitState(PyThreadState *tstate); extern int _PyWarnings_InitState(PyThreadState *tstate);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -114,37 +114,34 @@ init_filters(void)
} }
/* Initialize the given warnings module state. */ /* Initialize the given warnings module state. */
static int int
warnings_init_state(WarningsState *st) _PyWarnings_InitState(PyThreadState *tstate)
{ {
WarningsState *st = &tstate->interp->warnings;
if (st->filters == NULL) { if (st->filters == NULL) {
st->filters = init_filters(); st->filters = init_filters();
if (st->filters == NULL) { if (st->filters == NULL) {
goto error; return -1;
} }
} }
if (st->once_registry == NULL) { if (st->once_registry == NULL) {
st->once_registry = PyDict_New(); st->once_registry = PyDict_New();
if (st->once_registry == NULL) { if (st->once_registry == NULL) {
goto error; return -1;
} }
} }
if (st->default_action == NULL) { if (st->default_action == NULL) {
st->default_action = PyUnicode_FromString("default"); st->default_action = PyUnicode_FromString("default");
if (st->default_action == NULL) { if (st->default_action == NULL) {
goto error; return -1;
} }
} }
st->filters_version = 0; st->filters_version = 0;
return 0; return 0;
error:
warnings_clear_state(st);
return -1;
} }
@ -1367,16 +1364,6 @@ static struct PyModuleDef warningsmodule = {
}; };
PyStatus
_PyWarnings_InitState(PyThreadState *tstate)
{
if (warnings_init_state(&tstate->interp->warnings) < 0) {
return _PyStatus_ERR("can't initialize warnings");
}
return _PyStatus_OK();
}
PyMODINIT_FUNC PyMODINIT_FUNC
_PyWarnings_Init(void) _PyWarnings_Init(void)
{ {
@ -1391,9 +1378,6 @@ _PyWarnings_Init(void)
if (st == NULL) { if (st == NULL) {
goto error; goto error;
} }
if (warnings_init_state(st) < 0) {
goto error;
}
if (PyModule_AddObjectRef(m, "filters", st->filters) < 0) { if (PyModule_AddObjectRef(m, "filters", st->filters) < 0) {
goto error; goto error;

View File

@ -51,43 +51,6 @@ module _imp
/* Initialize things */ /* Initialize things */
PyStatus
_PyImportHooks_Init(PyThreadState *tstate)
{
PyObject *v, *path_hooks = NULL;
int err = 0;
/* adding sys.path_hooks and sys.path_importer_cache */
v = PyList_New(0);
if (v == NULL)
goto error;
err = PySys_SetObject("meta_path", v);
Py_DECREF(v);
if (err)
goto error;
v = PyDict_New();
if (v == NULL)
goto error;
err = PySys_SetObject("path_importer_cache", v);
Py_DECREF(v);
if (err)
goto error;
path_hooks = PyList_New(0);
if (path_hooks == NULL)
goto error;
err = PySys_SetObject("path_hooks", path_hooks);
if (err) {
goto error;
}
Py_DECREF(path_hooks);
return _PyStatus_OK();
error:
_PyErr_Print(tstate);
return _PyStatus_ERR("initializing sys.meta_path, sys.path_hooks, "
"or path_importer_cache failed");
}
PyStatus PyStatus
_PyImportZip_Init(PyThreadState *tstate) _PyImportZip_Init(PyThreadState *tstate)
{ {

View File

@ -135,59 +135,61 @@ Py_IsInitialized(void)
having the lock, but you cannot use multiple threads.) having the lock, but you cannot use multiple threads.)
*/ */
static int
static PyStatus
init_importlib(PyThreadState *tstate, PyObject *sysmod) init_importlib(PyThreadState *tstate, PyObject *sysmod)
{ {
PyObject *importlib; assert(!_PyErr_Occurred(tstate));
PyObject *impmod;
PyObject *value;
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
int verbose = _PyInterpreterState_GetConfig(interp)->verbose; int verbose = _PyInterpreterState_GetConfig(interp)->verbose;
/* Import _importlib through its frozen version, _frozen_importlib. */ // Import _importlib through its frozen version, _frozen_importlib.
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) { if (verbose) {
return _PyStatus_ERR("can't import _frozen_importlib");
}
else if (verbose) {
PySys_FormatStderr("import _frozen_importlib # frozen\n"); PySys_FormatStderr("import _frozen_importlib # frozen\n");
} }
importlib = PyImport_AddModule("_frozen_importlib"); if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
return -1;
}
PyObject *importlib = PyImport_AddModule("_frozen_importlib"); // borrowed
if (importlib == NULL) { if (importlib == NULL) {
return _PyStatus_ERR("couldn't get _frozen_importlib from sys.modules"); return -1;
} }
interp->importlib = importlib; interp->importlib = Py_NewRef(importlib);
Py_INCREF(interp->importlib);
interp->import_func = _PyDict_GetItemStringWithError(interp->builtins, "__import__"); PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins,
if (interp->import_func == NULL) "__import__");
return _PyStatus_ERR("__import__ not found"); if (import_func == NULL) {
Py_INCREF(interp->import_func); return -1;
/* Import the _imp module */
impmod = PyInit__imp();
if (impmod == NULL) {
return _PyStatus_ERR("can't import _imp");
} }
else if (verbose) { interp->import_func = Py_NewRef(import_func);
// Import the _imp module
if (verbose) {
PySys_FormatStderr("import _imp # builtin\n"); PySys_FormatStderr("import _imp # builtin\n");
} }
if (_PyImport_SetModuleString("_imp", impmod) < 0) { PyObject *imp_mod = PyInit__imp();
return _PyStatus_ERR("can't save _imp to sys.modules"); if (imp_mod == NULL) {
return -1;
}
if (_PyImport_SetModuleString("_imp", imp_mod) < 0) {
Py_DECREF(imp_mod);
return -1;
} }
/* Install importlib as the implementation of import */ // Install importlib as the implementation of import
value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod); PyObject *value = PyObject_CallMethod(importlib, "_install",
"OO", sysmod, imp_mod);
Py_DECREF(imp_mod);
if (value == NULL) { if (value == NULL) {
_PyErr_Print(tstate); return -1;
return _PyStatus_ERR("importlib install failed");
} }
Py_DECREF(value); Py_DECREF(value);
Py_DECREF(impmod);
return _PyStatus_OK(); assert(!_PyErr_Occurred(tstate));
return 0;
} }
static PyStatus static PyStatus
init_importlib_external(PyThreadState *tstate) init_importlib_external(PyThreadState *tstate)
{ {
@ -700,6 +702,9 @@ pycore_init_types(PyThreadState *tstate)
} }
} }
if (_PyWarnings_InitState(tstate) < 0) {
return _PyStatus_ERR("can't initialize warnings");
}
return _PyStatus_OK(); return _PyStatus_OK();
} }
@ -747,37 +752,6 @@ error:
} }
static PyStatus
pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
{
assert(!_PyErr_Occurred(tstate));
PyStatus status = _PyImportHooks_Init(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
/* Initialize _warnings. */
status = _PyWarnings_InitState(tstate);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
if (config->_install_importlib) {
/* This call sets up builtin and frozen import support */
status = init_importlib(tstate, sysmod);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
}
assert(!_PyErr_Occurred(tstate));
return _PyStatus_OK();
}
static PyStatus static PyStatus
pycore_interp_init(PyThreadState *tstate) pycore_interp_init(PyThreadState *tstate)
{ {
@ -789,6 +763,12 @@ pycore_interp_init(PyThreadState *tstate)
goto done; goto done;
} }
if (_Py_IsMainInterpreter(tstate)) {
if (_PyTime_Init() < 0) {
return _PyStatus_ERR("can't initialize time");
}
}
status = _PySys_Create(tstate, &sysmod); status = _PySys_Create(tstate, &sysmod);
if (_PyStatus_EXCEPTION(status)) { if (_PyStatus_EXCEPTION(status)) {
goto done; goto done;
@ -799,7 +779,13 @@ pycore_interp_init(PyThreadState *tstate)
goto done; goto done;
} }
status = pycore_init_import_warnings(tstate, sysmod); const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
if (config->_install_importlib) {
/* This call sets up builtin and frozen import support */
if (init_importlib(tstate, sysmod) < 0) {
return _PyStatus_ERR("failed to initialize importlib");
}
}
done: done:
/* sys.modules['sys'] contains a strong reference to the module */ /* sys.modules['sys'] contains a strong reference to the module */
@ -1044,12 +1030,6 @@ init_interp_main(PyThreadState *tstate)
return status; return status;
} }
if (is_main_interp) {
if (_PyTime_Init() < 0) {
return _PyStatus_ERR("can't initialize time");
}
}
if (interpreter_update_config(tstate, 1) < 0) { if (interpreter_update_config(tstate, 1) < 0) {
return _PyStatus_ERR("failed to update the Python config"); return _PyStatus_ERR("failed to update the Python config");
} }

View File

@ -2841,6 +2841,11 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
} }
} }
/* adding sys.path_hooks and sys.path_importer_cache */
SET_SYS("meta_path", PyList_New(0));
SET_SYS("path_importer_cache", PyDict_New());
SET_SYS("path_hooks", PyList_New(0));
if (_PyErr_Occurred(tstate)) { if (_PyErr_Occurred(tstate)) {
goto err_occurred; goto err_occurred;
} }