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:
parent
d19fa7a337
commit
ef75a625cd
|
@ -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;
|
||||||
|
|
|
@ -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 *);
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue