diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 3bffc80c937..1caeb98e993 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -14,6 +14,10 @@ PyAPI_FUNC(int) Py_SetStandardStreamEncoding(const char *encoding, /* PEP 432 Multi-phase initialization API (Private while provisional!) */ +PyAPI_FUNC(_PyInitError) _Py_PreInitialize(void); +PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPreConfig( + _PyPreConfig *preconfig); + PyAPI_FUNC(_PyInitError) _Py_InitializeCore( PyInterpreterState **interp, const _PyCoreConfig *); diff --git a/Include/internal/pycore_pystate.h b/Include/internal/pycore_pystate.h index 7c9d11aec36..911e7ee33ba 100644 --- a/Include/internal/pycore_pystate.h +++ b/Include/internal/pycore_pystate.h @@ -134,8 +134,15 @@ struct _gilstate_runtime_state { /* Full Python runtime state */ typedef struct pyruntimestate { - int initialized; + /* Is Python pre-initialized? Set to 1 by _Py_PreInitialize() */ + int pre_initialized; + + /* Is Python core initialized? Set to 1 by _Py_InitializeCore() */ int core_initialized; + + /* Is Python fully initialized? Set to 1 by Py_Initialize() */ + int initialized; + PyThreadState *finalizing; struct pyinterpreters { @@ -172,7 +179,8 @@ typedef struct pyruntimestate { // XXX Consolidate globals found via the check-c-globals script. } _PyRuntimeState; -#define _PyRuntimeState_INIT {.initialized = 0, .core_initialized = 0} +#define _PyRuntimeState_INIT \ + {.pre_initialized = 0, .core_initialized = 0, .initialized = 0} /* Note: _PyRuntimeState_INIT sets other fields to 0/NULL */ PyAPI_DATA(_PyRuntimeState) _PyRuntime; diff --git a/Modules/main.c b/Modules/main.c index df4eca5aae8..57cf862a30b 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -283,32 +283,30 @@ _PyMainInterpreterConfig_Read(_PyMainInterpreterConfig *main_config, /* --- pymain_init() ---------------------------------------------- */ static _PyInitError -preconfig_read_write(_PyPreConfig *config, const _PyArgv *args) +pymain_init_preconfig(_PyPreConfig *config, const _PyArgv *args) { - _PyPreConfig_GetGlobalConfig(config); - _PyInitError err = _PyPreConfig_ReadFromArgv(config, args); if (_Py_INIT_FAILED(err)) { return err; } - return _PyPreConfig_Write(config); + return _Py_PreInitializeFromPreConfig(config); } static _PyInitError -config_read_write(_PyCoreConfig *config, const _PyArgv *args, - const _PyPreConfig *preconfig) +pymain_init_coreconfig(_PyCoreConfig *config, const _PyArgv *args, + const _PyPreConfig *preconfig, + PyInterpreterState **interp_p) { - _PyCoreConfig_GetGlobalConfig(config); - _PyInitError err = _PyCoreConfig_ReadFromArgv(config, args, preconfig); if (_Py_INIT_FAILED(err)) { return err; } _PyCoreConfig_Write(config); - return _Py_INIT_OK(); + + return _Py_InitializeCore(interp_p, config); } @@ -356,24 +354,17 @@ pymain_init(const _PyArgv *args, PyInterpreterState **interp_p) _PyCoreConfig local_config = _PyCoreConfig_INIT; _PyCoreConfig *config = &local_config; - err = preconfig_read_write(preconfig, args); + err = pymain_init_preconfig(preconfig, args); if (_Py_INIT_FAILED(err)) { goto done; } - err = config_read_write(config, args, preconfig); + err = pymain_init_coreconfig(config, args, preconfig, interp_p); if (_Py_INIT_FAILED(err)) { goto done; } - PyInterpreterState *interp; - err = _Py_InitializeCore(&interp, config); - if (_Py_INIT_FAILED(err)) { - goto done; - } - *interp_p = interp; - - err = pymain_init_python_main(interp); + err = pymain_init_python_main(*interp_p); if (_Py_INIT_FAILED(err)) { goto done; } diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 08273765098..de2058c0f34 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -1367,6 +1367,11 @@ _PyCoreConfig_Read(_PyCoreConfig *config, const _PyPreConfig *preconfig) { _PyInitError err; + err = _Py_PreInitialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + _PyCoreConfig_GetGlobalConfig(config); if (preconfig != NULL) { @@ -2025,6 +2030,8 @@ config_from_cmdline(_PyCoreConfig *config, _PyCmdline *cmdline, int need_usage = 0; _PyInitError err; + _PyCoreConfig_GetGlobalConfig(config); + err = config_init_program(config, cmdline); if (_Py_INIT_FAILED(err)) { return err; diff --git a/Python/preconfig.c b/Python/preconfig.c index b03436181c8..a149ea54f65 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -672,6 +672,8 @@ _PyPreConfig_ReadFromArgv(_PyPreConfig *config, const _PyArgv *args) goto done; } + _PyPreConfig_GetGlobalConfig(config); + if (_PyPreConfig_Copy(&save_config, config) < 0) { err = _Py_INIT_NO_MEMORY(); goto done; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index df9570b2e48..994a94f1402 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -714,19 +714,57 @@ _Py_InitializeCore_impl(PyInterpreterState **interp_p, } -static _PyInitError -pyinit_preconfig(_PyPreConfig *preconfig, const _PyPreConfig *src_preconfig) +_PyInitError +_Py_PreInitializeFromPreConfig(_PyPreConfig *config) { - if (_PyPreConfig_Copy(preconfig, src_preconfig) < 0) { - return _Py_INIT_ERR("failed to copy pre config"); + if (config != NULL) { + _PyInitError err = _PyPreConfig_Write(config); + if (_Py_INIT_FAILED(err)) { + return err; + } } - _PyInitError err = _PyPreConfig_Read(preconfig); + _PyRuntime.pre_initialized = 1; + return _Py_INIT_OK(); +} + + +static _PyInitError +pyinit_preconfig(_PyPreConfig *config, const _PyPreConfig *src_config) +{ + _PyInitError err; + + err = _PyRuntime_Initialize(); if (_Py_INIT_FAILED(err)) { return err; } - return _PyPreConfig_Write(preconfig); + if (_PyPreConfig_Copy(config, src_config) < 0) { + return _Py_INIT_ERR("failed to copy pre config"); + } + + err = _PyPreConfig_Read(config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + return _Py_PreInitializeFromPreConfig(config); +} + + +_PyInitError +_Py_PreInitialize(void) +{ + _PyInitError err = _PyRuntime_Initialize(); + if (_Py_INIT_FAILED(err)) { + return err; + } + + if (_PyRuntime.pre_initialized) { + return _Py_INIT_OK(); + } + + return _Py_PreInitializeFromPreConfig(NULL); }