Skip to content

Commit ef75a62

Browse files
authored
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.
1 parent d19fa7a commit ef75a62

File tree

7 files changed

+68
-133
lines changed

7 files changed

+68
-133
lines changed

Include/internal/pycore_interp.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,14 @@ struct _is {
190190
struct _ceval_state ceval;
191191
struct _gc_runtime_state gc;
192192

193+
// sys.modules dictionary
193194
PyObject *modules;
194195
PyObject *modules_by_index;
196+
// Dictionary of the sys module
195197
PyObject *sysdict;
198+
// Dictionary of the builtins module
196199
PyObject *builtins;
200+
// importlib module
197201
PyObject *importlib;
198202

199203
/* Used in Modules/_threadmodule.c. */
@@ -218,7 +222,7 @@ struct _is {
218222

219223
PyObject *builtins_copy;
220224
PyObject *import_func;
221-
/* Initialized to PyEval_EvalFrameDefault(). */
225+
// Initialized to _PyEval_EvalFrameDefault().
222226
_PyFrameEvalFunction eval_frame;
223227

224228
Py_ssize_t co_extra_user_count;

Include/internal/pycore_pylifecycle.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ extern int _PySys_UpdateConfig(PyThreadState *tstate);
4848
extern PyStatus _PyExc_Init(PyThreadState *tstate);
4949
extern PyStatus _PyErr_Init(void);
5050
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
51-
extern PyStatus _PyImportHooks_Init(PyThreadState *tstate);
5251
extern int _PyFloat_Init(void);
5352
extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
5453

Include/internal/pycore_warnings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct _warnings_runtime_state {
1717
long filters_version;
1818
};
1919

20-
extern PyStatus _PyWarnings_InitState(PyThreadState *tstate);
20+
extern int _PyWarnings_InitState(PyThreadState *tstate);
2121

2222
#ifdef __cplusplus
2323
}

Python/_warnings.c

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -114,37 +114,34 @@ init_filters(void)
114114
}
115115

116116
/* Initialize the given warnings module state. */
117-
static int
118-
warnings_init_state(WarningsState *st)
117+
int
118+
_PyWarnings_InitState(PyThreadState *tstate)
119119
{
120+
WarningsState *st = &tstate->interp->warnings;
121+
120122
if (st->filters == NULL) {
121123
st->filters = init_filters();
122124
if (st->filters == NULL) {
123-
goto error;
125+
return -1;
124126
}
125127
}
126128

127129
if (st->once_registry == NULL) {
128130
st->once_registry = PyDict_New();
129131
if (st->once_registry == NULL) {
130-
goto error;
132+
return -1;
131133
}
132134
}
133135

134136
if (st->default_action == NULL) {
135137
st->default_action = PyUnicode_FromString("default");
136138
if (st->default_action == NULL) {
137-
goto error;
139+
return -1;
138140
}
139141
}
140142

141143
st->filters_version = 0;
142-
143144
return 0;
144-
145-
error:
146-
warnings_clear_state(st);
147-
return -1;
148145
}
149146

150147

@@ -1367,16 +1364,6 @@ static struct PyModuleDef warningsmodule = {
13671364
};
13681365

13691366

1370-
PyStatus
1371-
_PyWarnings_InitState(PyThreadState *tstate)
1372-
{
1373-
if (warnings_init_state(&tstate->interp->warnings) < 0) {
1374-
return _PyStatus_ERR("can't initialize warnings");
1375-
}
1376-
return _PyStatus_OK();
1377-
}
1378-
1379-
13801367
PyMODINIT_FUNC
13811368
_PyWarnings_Init(void)
13821369
{
@@ -1391,9 +1378,6 @@ _PyWarnings_Init(void)
13911378
if (st == NULL) {
13921379
goto error;
13931380
}
1394-
if (warnings_init_state(st) < 0) {
1395-
goto error;
1396-
}
13971381

13981382
if (PyModule_AddObjectRef(m, "filters", st->filters) < 0) {
13991383
goto error;

Python/import.c

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -51,43 +51,6 @@ module _imp
5151

5252
/* Initialize things */
5353

54-
PyStatus
55-
_PyImportHooks_Init(PyThreadState *tstate)
56-
{
57-
PyObject *v, *path_hooks = NULL;
58-
int err = 0;
59-
60-
/* adding sys.path_hooks and sys.path_importer_cache */
61-
v = PyList_New(0);
62-
if (v == NULL)
63-
goto error;
64-
err = PySys_SetObject("meta_path", v);
65-
Py_DECREF(v);
66-
if (err)
67-
goto error;
68-
v = PyDict_New();
69-
if (v == NULL)
70-
goto error;
71-
err = PySys_SetObject("path_importer_cache", v);
72-
Py_DECREF(v);
73-
if (err)
74-
goto error;
75-
path_hooks = PyList_New(0);
76-
if (path_hooks == NULL)
77-
goto error;
78-
err = PySys_SetObject("path_hooks", path_hooks);
79-
if (err) {
80-
goto error;
81-
}
82-
Py_DECREF(path_hooks);
83-
return _PyStatus_OK();
84-
85-
error:
86-
_PyErr_Print(tstate);
87-
return _PyStatus_ERR("initializing sys.meta_path, sys.path_hooks, "
88-
"or path_importer_cache failed");
89-
}
90-
9154
PyStatus
9255
_PyImportZip_Init(PyThreadState *tstate)
9356
{

Python/pylifecycle.c

Lines changed: 50 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -135,59 +135,61 @@ Py_IsInitialized(void)
135135
having the lock, but you cannot use multiple threads.)
136136
137137
*/
138-
139-
static PyStatus
138+
static int
140139
init_importlib(PyThreadState *tstate, PyObject *sysmod)
141140
{
142-
PyObject *importlib;
143-
PyObject *impmod;
144-
PyObject *value;
141+
assert(!_PyErr_Occurred(tstate));
142+
145143
PyInterpreterState *interp = tstate->interp;
146144
int verbose = _PyInterpreterState_GetConfig(interp)->verbose;
147145

148-
/* Import _importlib through its frozen version, _frozen_importlib. */
149-
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
150-
return _PyStatus_ERR("can't import _frozen_importlib");
151-
}
152-
else if (verbose) {
146+
// Import _importlib through its frozen version, _frozen_importlib.
147+
if (verbose) {
153148
PySys_FormatStderr("import _frozen_importlib # frozen\n");
154149
}
155-
importlib = PyImport_AddModule("_frozen_importlib");
150+
if (PyImport_ImportFrozenModule("_frozen_importlib") <= 0) {
151+
return -1;
152+
}
153+
PyObject *importlib = PyImport_AddModule("_frozen_importlib"); // borrowed
156154
if (importlib == NULL) {
157-
return _PyStatus_ERR("couldn't get _frozen_importlib from sys.modules");
155+
return -1;
158156
}
159-
interp->importlib = importlib;
160-
Py_INCREF(interp->importlib);
161-
162-
interp->import_func = _PyDict_GetItemStringWithError(interp->builtins, "__import__");
163-
if (interp->import_func == NULL)
164-
return _PyStatus_ERR("__import__ not found");
165-
Py_INCREF(interp->import_func);
157+
interp->importlib = Py_NewRef(importlib);
166158

167-
/* Import the _imp module */
168-
impmod = PyInit__imp();
169-
if (impmod == NULL) {
170-
return _PyStatus_ERR("can't import _imp");
159+
PyObject *import_func = _PyDict_GetItemStringWithError(interp->builtins,
160+
"__import__");
161+
if (import_func == NULL) {
162+
return -1;
171163
}
172-
else if (verbose) {
164+
interp->import_func = Py_NewRef(import_func);
165+
166+
// Import the _imp module
167+
if (verbose) {
173168
PySys_FormatStderr("import _imp # builtin\n");
174169
}
175-
if (_PyImport_SetModuleString("_imp", impmod) < 0) {
176-
return _PyStatus_ERR("can't save _imp to sys.modules");
170+
PyObject *imp_mod = PyInit__imp();
171+
if (imp_mod == NULL) {
172+
return -1;
173+
}
174+
if (_PyImport_SetModuleString("_imp", imp_mod) < 0) {
175+
Py_DECREF(imp_mod);
176+
return -1;
177177
}
178178

179-
/* Install importlib as the implementation of import */
180-
value = PyObject_CallMethod(importlib, "_install", "OO", sysmod, impmod);
179+
// Install importlib as the implementation of import
180+
PyObject *value = PyObject_CallMethod(importlib, "_install",
181+
"OO", sysmod, imp_mod);
182+
Py_DECREF(imp_mod);
181183
if (value == NULL) {
182-
_PyErr_Print(tstate);
183-
return _PyStatus_ERR("importlib install failed");
184+
return -1;
184185
}
185186
Py_DECREF(value);
186-
Py_DECREF(impmod);
187187

188-
return _PyStatus_OK();
188+
assert(!_PyErr_Occurred(tstate));
189+
return 0;
189190
}
190191

192+
191193
static PyStatus
192194
init_importlib_external(PyThreadState *tstate)
193195
{
@@ -700,6 +702,9 @@ pycore_init_types(PyThreadState *tstate)
700702
}
701703
}
702704

705+
if (_PyWarnings_InitState(tstate) < 0) {
706+
return _PyStatus_ERR("can't initialize warnings");
707+
}
703708
return _PyStatus_OK();
704709
}
705710

@@ -747,37 +752,6 @@ pycore_init_builtins(PyThreadState *tstate)
747752
}
748753

749754

750-
static PyStatus
751-
pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod)
752-
{
753-
assert(!_PyErr_Occurred(tstate));
754-
755-
PyStatus status = _PyImportHooks_Init(tstate);
756-
if (_PyStatus_EXCEPTION(status)) {
757-
return status;
758-
}
759-
760-
/* Initialize _warnings. */
761-
status = _PyWarnings_InitState(tstate);
762-
if (_PyStatus_EXCEPTION(status)) {
763-
return status;
764-
}
765-
766-
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
767-
if (config->_install_importlib) {
768-
/* This call sets up builtin and frozen import support */
769-
status = init_importlib(tstate, sysmod);
770-
if (_PyStatus_EXCEPTION(status)) {
771-
return status;
772-
}
773-
}
774-
775-
assert(!_PyErr_Occurred(tstate));
776-
777-
return _PyStatus_OK();
778-
}
779-
780-
781755
static PyStatus
782756
pycore_interp_init(PyThreadState *tstate)
783757
{
@@ -789,6 +763,12 @@ pycore_interp_init(PyThreadState *tstate)
789763
goto done;
790764
}
791765

766+
if (_Py_IsMainInterpreter(tstate)) {
767+
if (_PyTime_Init() < 0) {
768+
return _PyStatus_ERR("can't initialize time");
769+
}
770+
}
771+
792772
status = _PySys_Create(tstate, &sysmod);
793773
if (_PyStatus_EXCEPTION(status)) {
794774
goto done;
@@ -799,7 +779,13 @@ pycore_interp_init(PyThreadState *tstate)
799779
goto done;
800780
}
801781

802-
status = pycore_init_import_warnings(tstate, sysmod);
782+
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
783+
if (config->_install_importlib) {
784+
/* This call sets up builtin and frozen import support */
785+
if (init_importlib(tstate, sysmod) < 0) {
786+
return _PyStatus_ERR("failed to initialize importlib");
787+
}
788+
}
803789

804790
done:
805791
/* sys.modules['sys'] contains a strong reference to the module */
@@ -1044,12 +1030,6 @@ init_interp_main(PyThreadState *tstate)
10441030
return status;
10451031
}
10461032

1047-
if (is_main_interp) {
1048-
if (_PyTime_Init() < 0) {
1049-
return _PyStatus_ERR("can't initialize time");
1050-
}
1051-
}
1052-
10531033
if (interpreter_update_config(tstate, 1) < 0) {
10541034
return _PyStatus_ERR("failed to update the Python config");
10551035
}

Python/sysmodule.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2841,6 +2841,11 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
28412841
}
28422842
}
28432843

2844+
/* adding sys.path_hooks and sys.path_importer_cache */
2845+
SET_SYS("meta_path", PyList_New(0));
2846+
SET_SYS("path_importer_cache", PyDict_New());
2847+
SET_SYS("path_hooks", PyList_New(0));
2848+
28442849
if (_PyErr_Occurred(tstate)) {
28452850
goto err_occurred;
28462851
}

0 commit comments

Comments
 (0)