From 484f20d2ff95cc2e1bea759852da307bc1d1d944 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 27 Mar 2019 02:04:16 +0100 Subject: [PATCH] bpo-36444: Add _PyCoreConfig._init_main (GH-12572) * Add _PyCoreConfig._init_main: if equals to zero, _Py_InitializeFromConfig() doesn't call _Py_InitializeMainInterpreter(). * Add interp_p parameter to _Py_InitializeFromConfig(). * pymain_init() now calls _Py_InitializeFromConfig(). * Make _Py_InitializeCore() private. --- Include/cpython/coreconfig.h | 6 +++++- Include/cpython/pylifecycle.h | 6 ++---- Lib/test/test_embed.py | 1 + Modules/main.c | 39 ++++++++++++++--------------------- Programs/_freeze_importlib.c | 3 ++- Programs/_testembed.c | 10 ++++----- Python/coreconfig.c | 2 ++ Python/frozenmain.c | 2 +- Python/pylifecycle.c | 24 ++++++++++++--------- 9 files changed, 47 insertions(+), 46 deletions(-) diff --git a/Include/cpython/coreconfig.h b/Include/cpython/coreconfig.h index 827a19a145d..53493ff85a3 100644 --- a/Include/cpython/coreconfig.h +++ b/Include/cpython/coreconfig.h @@ -365,6 +365,9 @@ typedef struct { If set to -1 (default), inherit Py_FrozenFlag value. */ int _frozen; + /* If non-zero, use "main" Python initialization */ + int _init_main; + } _PyCoreConfig; #ifdef MS_WINDOWS @@ -398,7 +401,8 @@ typedef struct { .buffered_stdio = -1, \ ._install_importlib = 1, \ ._check_hash_pycs_mode = "default", \ - ._frozen = -1} + ._frozen = -1, \ + ._init_main = 1} /* Note: _PyCoreConfig_INIT sets other fields to 0/NULL */ diff --git a/Include/cpython/pylifecycle.h b/Include/cpython/pylifecycle.h index 1db1d2167cb..496dcb2c604 100644 --- a/Include/cpython/pylifecycle.h +++ b/Include/cpython/pylifecycle.h @@ -20,9 +20,6 @@ PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromPreConfig( PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromConfig( const _PyCoreConfig *coreconfig); -PyAPI_FUNC(_PyInitError) _Py_InitializeCore( - const _PyCoreConfig *config, - PyInterpreterState **interp); PyAPI_FUNC(int) _Py_IsCoreInitialized(void); @@ -32,7 +29,8 @@ PyAPI_FUNC(_PyInitError) _Py_InitializeMainInterpreter( /* Initialization and finalization */ PyAPI_FUNC(_PyInitError) _Py_InitializeFromConfig( - const _PyCoreConfig *config); + const _PyCoreConfig *config, + PyInterpreterState **interp_p); PyAPI_FUNC(void) _Py_NO_RETURN _Py_ExitInitError(_PyInitError err); /* Py_PyAtExit is for the atexit module, Py_AtExit is for low-level diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py index f5e3cef68a5..c63ea5a45e4 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -338,6 +338,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): '_install_importlib': 1, '_check_hash_pycs_mode': 'default', '_frozen': 0, + '_init_main': 1, } if MS_WINDOWS: DEFAULT_PRE_CONFIG.update({ diff --git a/Modules/main.c b/Modules/main.c index 05b42cbc6c8..57d16093dca 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -53,19 +53,6 @@ done: } -static _PyInitError -pymain_init_coreconfig(_PyCoreConfig *config, const _PyArgv *args, - PyInterpreterState **interp_p) -{ - _PyInitError err = _PyCoreConfig_Read(config, args); - if (_Py_INIT_FAILED(err)) { - return err; - } - - return _Py_InitializeCore(config, interp_p); -} - - static _PyInitError pymain_init(const _PyArgv *args, PyInterpreterState **interp_p) { @@ -91,18 +78,22 @@ pymain_init(const _PyArgv *args, PyInterpreterState **interp_p) } _PyCoreConfig config = _PyCoreConfig_INIT; - err = pymain_init_coreconfig(&config, args, interp_p); + + err = _PyCoreConfig_Read(&config, args); + if (_Py_INIT_FAILED(err)) { + goto done; + } + + err = _Py_InitializeFromConfig(&config, interp_p); + if (_Py_INIT_FAILED(err)) { + goto done; + } + + err = _Py_INIT_OK(); + +done: _PyCoreConfig_Clear(&config); - if (_Py_INIT_FAILED(err)) { - return err; - } - - err = _Py_InitializeMainInterpreter(*interp_p); - if (_Py_INIT_FAILED(err)) { - return err; - } - - return _Py_INIT_OK(); + return err; } diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 0818012d8c5..774748dc091 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -84,8 +84,9 @@ main(int argc, char *argv[]) /* Don't install importlib, since it could execute outdated bytecode. */ config._install_importlib = 0; config._frozen = 1; + config._init_main = 0; - _PyInitError err = _Py_InitializeFromConfig(&config); + _PyInitError err = _Py_InitializeFromConfig(&config, NULL); /* No need to call _PyCoreConfig_Clear() since we didn't allocate any memory: program_name is a constant string. */ if (_Py_INIT_FAILED(err)) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index 76de8aab5ba..70587990f8d 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -529,7 +529,7 @@ static int test_init_from_config(void) Py_FrozenFlag = 0; config._frozen = 1; - err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config, NULL); /* Don't call _PyCoreConfig_Clear() since all strings are static */ if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); @@ -638,7 +638,7 @@ static int test_init_isolated(void) config.program_name = L"./_testembed"; test_init_env_dev_mode_putenvs(); - err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config, NULL); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); } @@ -669,7 +669,7 @@ static int test_preinit_isolated1(void) config.program_name = L"./_testembed"; test_init_env_dev_mode_putenvs(); - err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config, NULL); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); } @@ -706,7 +706,7 @@ static int test_preinit_isolated2(void) config.program_name = L"./_testembed"; test_init_env_dev_mode_putenvs(); - err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config, NULL); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); } @@ -723,7 +723,7 @@ static int test_init_dev_mode(void) putenv("PYTHONMALLOC="); config.dev_mode = 1; config.program_name = L"./_testembed"; - _PyInitError err = _Py_InitializeFromConfig(&config); + _PyInitError err = _Py_InitializeFromConfig(&config, NULL); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); } diff --git a/Python/coreconfig.c b/Python/coreconfig.c index 944a9e22ca1..ecb22e5667d 100644 --- a/Python/coreconfig.c +++ b/Python/coreconfig.c @@ -610,6 +610,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2) COPY_WSTR_ATTR(run_filename); COPY_ATTR(_check_hash_pycs_mode); COPY_ATTR(_frozen); + COPY_ATTR(_init_main); #undef COPY_ATTR #undef COPY_STR_ATTR @@ -715,6 +716,7 @@ _PyCoreConfig_AsDict(const _PyCoreConfig *config) SET_ITEM_INT(_install_importlib); SET_ITEM_STR(_check_hash_pycs_mode); SET_ITEM_INT(_frozen); + SET_ITEM_INT(_init_main); return dict; diff --git a/Python/frozenmain.c b/Python/frozenmain.c index 6554aa75b03..041b4670ca3 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -82,7 +82,7 @@ Py_FrozenMain(int argc, char **argv) if (argc >= 1) Py_SetProgramName(argv_copy[0]); - err = _Py_InitializeFromConfig(&config); + err = _Py_InitializeFromConfig(&config, NULL); /* No need to call _PyCoreConfig_Clear() since we didn't allocate any memory: program_name is a constant string. */ if (_Py_INIT_FAILED(err)) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index ca90e7238b6..f255fd9e132 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -458,7 +458,7 @@ _Py_SetLocaleFromEnv(int category) /* Global initializations. Can be undone by Py_Finalize(). Don't call this twice without an intervening Py_Finalize() call. - Every call to _Py_InitializeCore, Py_Initialize or Py_InitializeEx + Every call to _Py_InitializeFromConfig, Py_Initialize or Py_InitializeEx must have a corresponding call to Py_Finalize. Locking: you must hold the interpreter lock while calling these APIs. @@ -832,7 +832,7 @@ pyinit_coreconfig(_PyCoreConfig *config, const _PyCoreConfig *src_config, * to the Python C API (unless the API is explicitly listed as being * safe to call without calling Py_Initialize first) */ -_PyInitError +static _PyInitError _Py_InitializeCore(const _PyCoreConfig *src_config, PyInterpreterState **interp_p) { @@ -981,7 +981,8 @@ _Py_InitializeMainInterpreter(PyInterpreterState *interp) #undef _INIT_DEBUG_PRINT _PyInitError -_Py_InitializeFromConfig(const _PyCoreConfig *config) +_Py_InitializeFromConfig(const _PyCoreConfig *config, + PyInterpreterState **interp_p) { PyInterpreterState *interp = NULL; _PyInitError err; @@ -989,12 +990,18 @@ _Py_InitializeFromConfig(const _PyCoreConfig *config) if (_Py_INIT_FAILED(err)) { return err; } + if (interp_p) { + *interp_p = interp; + } config = &interp->core_config; - err = _Py_InitializeMainInterpreter(interp); - if (_Py_INIT_FAILED(err)) { - return err; + if (config->_init_main) { + err = _Py_InitializeMainInterpreter(interp); + if (_Py_INIT_FAILED(err)) { + return err; + } } + return _Py_INIT_OK(); } @@ -1007,13 +1014,10 @@ Py_InitializeEx(int install_sigs) return; } - _PyInitError err; _PyCoreConfig config = _PyCoreConfig_INIT; config.install_signal_handlers = install_sigs; - err = _Py_InitializeFromConfig(&config); - _PyCoreConfig_Clear(&config); - + _PyInitError err = _Py_InitializeFromConfig(&config, NULL); if (_Py_INIT_FAILED(err)) { _Py_ExitInitError(err); }