Skip to content

Commit f29084d

Browse files
authored
bpo-36301: Add _PyRuntime.pre_initialized (GH-12457)
* Add _PyRuntime.pre_initialized: set to 1 when Python is pre-initialized * Add _Py_PreInitialize() and _Py_PreInitializeFromPreConfig(). * _PyCoreConfig_Read() now calls _Py_PreInitialize(). * Move _PyPreConfig_GetGlobalConfig() and _PyCoreConfig_GetGlobalConfig() calls from main.c to preconfig.c and coreconfig.c.
1 parent 0d765e3 commit f29084d

6 files changed

Lines changed: 75 additions & 25 deletions

File tree

‎Include/cpython/pylifecycle.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding,
1414

1515
/* PEP 432 Multi-phase initialization API (Private while provisional!) */
1616

17+
PyAPI_FUNC(_PyInitError) _Py_PreInitialize(void);
18+
PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPreConfig(
19+
_PyPreConfig *preconfig);
20+
1721
PyAPI_FUNC(_PyInitError) _Py_InitializeCore(
1822
PyInterpreterState **interp,
1923
const _PyCoreConfig *);

‎Include/internal/pycore_pystate.h‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,15 @@ struct _gilstate_runtime_state {
134134
/* Full Python runtime state */
135135

136136
typedef struct pyruntimestate {
137-
int initialized;
137+
/* Is Python pre-initialized? Set to 1 by _Py_PreInitialize() */
138+
int pre_initialized;
139+
140+
/* Is Python core initialized? Set to 1 by _Py_InitializeCore() */
138141
int core_initialized;
142+
143+
/* Is Python fully initialized? Set to 1 by Py_Initialize() */
144+
int initialized;
145+
139146
PyThreadState *finalizing;
140147

141148
struct pyinterpreters {
@@ -172,7 +179,8 @@ typedef struct pyruntimestate {
172179
// XXX Consolidate globals found via the check-c-globals script.
173180
} _PyRuntimeState;
174181

175-
#define _PyRuntimeState_INIT {.initialized = 0, .core_initialized = 0}
182+
#define _PyRuntimeState_INIT \
183+
{.pre_initialized = 0, .core_initialized = 0, .initialized = 0}
176184
/* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */
177185

178186
PyAPI_DATA(_PyRuntimeState) _PyRuntime;

‎Modules/main.c‎

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -283,32 +283,30 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config,
283283
/* --- pymain_init() ---------------------------------------------- */
284284

285285
static _PyInitError
286-
preconfig_read_write(_PyPreConfig *config, const _PyArgv *args)
286+
pymain_init_preconfig(_PyPreConfig *config, const _PyArgv *args)
287287
{
288-
_PyPreConfig_GetGlobalConfig(config);
289-
290288
_PyInitError err = _PyPreConfig_ReadFromArgv(config, args);
291289
if (_Py_INIT_FAILED(err)) {
292290
return err;
293291
}
294292

295-
return _PyPreConfig_Write(config);
293+
return _Py_PreInitializeFromPreConfig(config);
296294
}
297295

298296

299297
static _PyInitError
300-
config_read_write(_PyCoreConfig *config, const _PyArgv *args,
301-
const _PyPreConfig *preconfig)
298+
pymain_init_coreconfig(_PyCoreConfig *config, const _PyArgv *args,
299+
const _PyPreConfig *preconfig,
300+
PyInterpreterState **interp_p)
302301
{
303-
_PyCoreConfig_GetGlobalConfig(config);
304-
305302
_PyInitError err = _PyCoreConfig_ReadFromArgv(config, args, preconfig);
306303
if (_Py_INIT_FAILED(err)) {
307304
return err;
308305
}
309306

310307
_PyCoreConfig_Write(config);
311-
return _Py_INIT_OK();
308+
309+
return _Py_InitializeCore(interp_p, config);
312310
}
313311

314312

@@ -356,24 +354,17 @@ pymain_init(const _PyArgv *args, PyInterpreterState **interp_p)
356354
_PyCoreConfig local_config = _PyCoreConfig_INIT;
357355
_PyCoreConfig *config = &local_config;
358356

359-
err = preconfig_read_write(preconfig, args);
357+
err = pymain_init_preconfig(preconfig, args);
360358
if (_Py_INIT_FAILED(err)) {
361359
goto done;
362360
}
363361

364-
err = config_read_write(config, args, preconfig);
365-
if (_Py_INIT_FAILED(err)) {
366-
goto done;
367-
}
368-
369-
PyInterpreterState *interp;
370-
err = _Py_InitializeCore(&interp, config);
362+
err = pymain_init_coreconfig(config, args, preconfig, interp_p);
371363
if (_Py_INIT_FAILED(err)) {
372364
goto done;
373365
}
374-
*interp_p = interp;
375366

376-
err = pymain_init_python_main(interp);
367+
err = pymain_init_python_main(*interp_p);
377368
if (_Py_INIT_FAILED(err)) {
378369
goto done;
379370
}

‎Python/coreconfig.c‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,11 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig)
13671367
{
13681368
_PyInitError err;
13691369

1370+
err = _Py_PreInitialize();
1371+
if (_Py_INIT_FAILED(err)) {
1372+
return err;
1373+
}
1374+
13701375
_PyCoreConfig_GetGlobalConfig(config);
13711376

13721377
if (preconfig != NULL) {
@@ -2025,6 +2030,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline,
20252030
int need_usage = 0;
20262031
_PyInitError err;
20272032

2033+
_PyCoreConfig_GetGlobalConfig(config);
2034+
20282035
err = config_init_program(config, cmdline);
20292036
if (_Py_INIT_FAILED(err)) {
20302037
return err;

‎Python/preconfig.c‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,8 @@ _PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args)
672672
goto done;
673673
}
674674

675+
_PyPreConfig_GetGlobalConfig(config);
676+
675677
if (_PyPreConfig_Copy(&save_config, config) < 0) {
676678
err = _Py_INIT_NO_MEMORY();
677679
goto done;

‎Python/pylifecycle.c‎

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -714,19 +714,57 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p,
714714
}
715715

716716

717+
_PyInitError
718+
_Py_PreInitializeFromPreConfig(_PyPreConfig *config)
719+
{
720+
if (config != NULL) {
721+
_PyInitError err = _PyPreConfig_Write(config);
722+
if (_Py_INIT_FAILED(err)) {
723+
return err;
724+
}
725+
}
726+
727+
_PyRuntime.pre_initialized = 1;
728+
return _Py_INIT_OK();
729+
}
730+
731+
717732
static _PyInitError
718-
pyinit_preconfig(_PyPreConfig *preconfig, const _PyPreConfig *src_preconfig)
733+
pyinit_preconfig(_PyPreConfig *config, const _PyPreConfig *src_config)
719734
{
720-
if (_PyPreConfig_Copy(preconfig, src_preconfig) < 0) {
735+
_PyInitError err;
736+
737+
err = _PyRuntime_Initialize();
738+
if (_Py_INIT_FAILED(err)) {
739+
return err;
740+
}
741+
742+
if (_PyPreConfig_Copy(config, src_config) < 0) {
721743
return _Py_INIT_ERR("failed to copy pre config");
722744
}
723745

724-
_PyInitError err = _PyPreConfig_Read(preconfig);
746+
err = _PyPreConfig_Read(config);
725747
if (_Py_INIT_FAILED(err)) {
726748
return err;
727749
}
728750

729-
return _PyPreConfig_Write(preconfig);
751+
return _Py_PreInitializeFromPreConfig(config);
752+
}
753+
754+
755+
_PyInitError
756+
_Py_PreInitialize(void)
757+
{
758+
_PyInitError err = _PyRuntime_Initialize();
759+
if (_Py_INIT_FAILED(err)) {
760+
return err;
761+
}
762+
763+
if (_PyRuntime.pre_initialized) {
764+
return _Py_INIT_OK();
765+
}
766+
767+
return _Py_PreInitializeFromPreConfig(NULL);
730768
}
731769

732770

0 commit comments

Comments
 (0)