From webhook-mailer at python.org Tue Oct 1 04:56:42 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 01 Oct 2019 08:56:42 -0000 Subject: [Python-checkins] bpo-38304: Remove PyConfig.struct_size (GH-16500) (GH-16508) Message-ID: https://github.com/python/cpython/commit/3c30a76f3d3c0dcc1fb4de097fa4a3a4c92c0b0b commit: 3c30a76f3d3c0dcc1fb4de097fa4a3a4c92c0b0b branch: master author: Victor Stinner committer: GitHub date: 2019-10-01T10:56:37+02:00 summary: bpo-38304: Remove PyConfig.struct_size (GH-16500) (GH-16508) For now, we'll rely on the fact that the config structures aren't covered by the stable ABI. We may revisit this in the future if we further explore the idea of offering a stable embedding API. (cherry picked from commit bdace21b769998396d0ccc8da99a8ca9b507bfdf) files: D Misc/NEWS.d/next/C API/2019-09-28-03-43-27.bpo-38304.RqHAwd.rst M Doc/c-api/init_config.rst M Include/cpython/initconfig.h M Include/internal/pycore_initconfig.h M Modules/main.c M PC/python_uwp.cpp M Programs/_freeze_importlib.c M Programs/_testembed.c M Python/frozenmain.c M Python/initconfig.c M Python/pathconfig.c M Python/preconfig.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 4c77d5d1e0e8..15b8b94d5a74 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -194,25 +194,18 @@ PyPreConfig * Configure the LC_CTYPE locale * Set the UTF-8 mode - The :c:member:`struct_size` field must be explicitly initialized to - ``sizeof(PyPreConfig)``. - Function to initialize a preconfiguration: - .. c:function:: PyStatus PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig) + .. c:function:: void PyPreConfig_InitIsolatedConfig(PyPreConfig *preconfig) Initialize the preconfiguration with :ref:`Python Configuration `. - .. c:function:: PyStatus PyPreConfig_InitPythonConfig(PyPreConfig *preconfig) + .. c:function:: void PyPreConfig_InitPythonConfig(PyPreConfig *preconfig) Initialize the preconfiguration with :ref:`Isolated Configuration `. - The caller of these functions is responsible to handle exceptions (error or - exit) using :c:func:`PyStatus_Exception` and - :c:func:`Py_ExitStatusException`. - Structure fields: .. c:member:: int allocator @@ -274,13 +267,6 @@ PyPreConfig same way the regular Python parses command line arguments: see :ref:`Command Line Arguments `. - .. c:member:: size_t struct_size - - Size of the structure in bytes: must be initialized to - ``sizeof(PyPreConfig)``. - - Field used for API and ABI compatibility. - .. c:member:: int use_environment See :c:member:`PyConfig.use_environment`. @@ -332,12 +318,7 @@ Example using the preinitialization to enable the UTF-8 Mode:: PyStatus status; PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitPythonConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyPreConfig_InitPythonConfig(&preconfig); preconfig.utf8_mode = 1; @@ -360,9 +341,6 @@ PyConfig Structure containing most parameters to configure Python. - The :c:member:`struct_size` field must be explicitly initialized to - ``sizeof(PyConfig)``. - Structure methods: .. c:function:: PyStatus PyConfig_InitPythonConfig(PyConfig *config) @@ -679,13 +657,6 @@ PyConfig Encoding and encoding errors of :data:`sys.stdin`, :data:`sys.stdout` and :data:`sys.stderr`. - .. c:member:: size_t struct_size - - Size of the structure in bytes: must be initialized to - ``sizeof(PyConfig)``. - - Field used for API and ABI compatibility. - .. c:member:: int tracemalloc If non-zero, call :func:`tracemalloc.start` at startup. @@ -754,7 +725,6 @@ Example setting the program name:: { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -787,7 +757,6 @@ configuration, and then override some parameters:: { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -875,7 +844,6 @@ Example of customized Python always running in isolated mode:: { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1067,7 +1035,6 @@ phases:: { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 8ce5622c5c40..25e02cea10dc 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -45,10 +45,6 @@ PyAPI_FUNC(PyStatus) PyWideStringList_Insert(PyWideStringList *list, /* --- PyPreConfig ----------------------------------------------- */ typedef struct { - /* Size of the structure in bytes: must be initialized to - sizeof(PyPreConfig). Field used for API and ABI compatibility. */ - size_t struct_size; - int _config_init; /* _PyConfigInitEnum value */ /* Parse Py_PreInitializeFromBytesArgs() arguments? @@ -124,17 +120,13 @@ typedef struct { int allocator; } PyPreConfig; -PyAPI_FUNC(PyStatus) PyPreConfig_InitPythonConfig(PyPreConfig *config); -PyAPI_FUNC(PyStatus) PyPreConfig_InitIsolatedConfig(PyPreConfig *config); +PyAPI_FUNC(void) PyPreConfig_InitPythonConfig(PyPreConfig *config); +PyAPI_FUNC(void) PyPreConfig_InitIsolatedConfig(PyPreConfig *config); /* --- PyConfig ---------------------------------------------- */ typedef struct { - /* Size of the structure in bytes: must be initialized to - sizeof(PyConfig). Field used for API and ABI compatibility. */ - size_t struct_size; - int _config_init; /* _PyConfigInitEnum value */ int isolated; /* Isolated mode? see PyPreConfig.isolated */ diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index eb6490f5a87f..e9810bcf90a8 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -120,8 +120,8 @@ extern PyStatus _PyPreCmdline_Read(_PyPreCmdline *cmdline, /* --- PyPreConfig ----------------------------------------------- */ -PyAPI_FUNC(PyStatus) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig); -extern PyStatus _PyPreConfig_InitFromConfig( +PyAPI_FUNC(void) _PyPreConfig_InitCompatConfig(PyPreConfig *preconfig); +extern void _PyPreConfig_InitFromConfig( PyPreConfig *preconfig, const PyConfig *config); extern PyStatus _PyPreConfig_InitFromPreConfig( diff --git a/Misc/NEWS.d/next/C API/2019-09-28-03-43-27.bpo-38304.RqHAwd.rst b/Misc/NEWS.d/next/C API/2019-09-28-03-43-27.bpo-38304.RqHAwd.rst deleted file mode 100644 index b797933d05d6..000000000000 --- a/Misc/NEWS.d/next/C API/2019-09-28-03-43-27.bpo-38304.RqHAwd.rst +++ /dev/null @@ -1,3 +0,0 @@ -Add a new ``struct_size`` field to :c:type:`PyPreConfig` and :c:type:`PyConfig` -structures to allow to modify these structures in the future without breaking -the backward compatibility. diff --git a/Modules/main.c b/Modules/main.c index ef6c66a8dbe5..9cbf3ac7060b 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -53,12 +53,7 @@ pymain_init(const _PyArgv *args) #endif PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitPythonConfig(&preconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + PyPreConfig_InitPythonConfig(&preconfig); status = _Py_PreInitializeFromPyArgv(&preconfig, args); if (_PyStatus_EXCEPTION(status)) { @@ -66,7 +61,7 @@ pymain_init(const _PyArgv *args) } PyConfig config; - config.struct_size = sizeof(PyConfig); + status = PyConfig_InitPythonConfig(&config); if (_PyStatus_EXCEPTION(status)) { goto done; diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp index 2656d188c250..758c8f73725e 100644 --- a/PC/python_uwp.cpp +++ b/PC/python_uwp.cpp @@ -165,12 +165,8 @@ int wmain(int argc, wchar_t **argv) { PyStatus status; - PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - PyConfig config; - config.struct_size = sizeof(PyConfig); const wchar_t *moduleName = NULL; const wchar_t *p = wcsrchr(argv[0], L'\\'); @@ -189,10 +185,7 @@ wmain(int argc, wchar_t **argv) } } - status = PyPreConfig_InitPythonConfig(&preconfig); - if (PyStatus_Exception(status)) { - goto fail_without_config; - } + PyPreConfig_InitPythonConfig(&preconfig); if (!moduleName) { status = Py_PreInitializeFromArgs(&preconfig, argc, argv); if (PyStatus_Exception(status)) { diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 7c494c2786c0..74735f279c58 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -78,7 +78,6 @@ main(int argc, char *argv[]) PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitIsolatedConfig(&config); if (PyStatus_Exception(status)) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index c8600d58f0b4..d2d4c7f8c651 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -385,12 +385,7 @@ static int check_init_compat_config(int preinit) if (preinit) { PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = _PyPreConfig_InitCompatConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyPreConfig_InitCompatConfig(&preconfig); status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { @@ -399,7 +394,6 @@ static int check_init_compat_config(int preinit) } PyConfig config; - config.struct_size = sizeof(PyConfig); status = _PyConfig_InitCompatConfig(&config); if (PyStatus_Exception(status)) { @@ -478,15 +472,8 @@ static int test_init_global_config(void) static int test_init_from_config(void) { - PyStatus status; - PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = _PyPreConfig_InitCompatConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyPreConfig_InitCompatConfig(&preconfig); putenv("PYTHONMALLOC=malloc_debug"); preconfig.allocator = PYMEM_ALLOCATOR_MALLOC; @@ -495,13 +482,12 @@ static int test_init_from_config(void) Py_UTF8Mode = 0; preconfig.utf8_mode = 1; - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } PyConfig config; - config.struct_size = sizeof(PyConfig); status = _PyConfig_InitCompatConfig(&config); if (PyStatus_Exception(status)) { @@ -638,7 +624,6 @@ static int check_init_parse_argv(int parse_argv) PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -725,7 +710,6 @@ static int test_init_python_env(void) set_all_env_vars(); PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -780,7 +764,6 @@ static int test_init_isolated_flag(void) /* Test PyConfig.isolated=1 */ PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -803,25 +786,17 @@ static int test_init_isolated_flag(void) /* PyPreConfig.isolated=1, PyConfig.isolated=0 */ static int test_preinit_isolated1(void) { - PyStatus status; - PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = _PyPreConfig_InitCompatConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyPreConfig_InitCompatConfig(&preconfig); preconfig.isolated = 1; - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } PyConfig config; - config.struct_size = sizeof(PyConfig); status = _PyConfig_InitCompatConfig(&config); if (PyStatus_Exception(status)) { @@ -840,26 +815,19 @@ static int test_preinit_isolated1(void) /* PyPreConfig.isolated=0, PyConfig.isolated=1 */ static int test_preinit_isolated2(void) { - PyStatus status; - PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = _PyPreConfig_InitCompatConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyPreConfig_InitCompatConfig(&preconfig); preconfig.isolated = 0; - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } /* Test PyConfig.isolated=1 */ PyConfig config; - config.struct_size = sizeof(PyConfig); + status = _PyConfig_InitCompatConfig(&config); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); @@ -880,15 +848,8 @@ static int test_preinit_isolated2(void) static int test_preinit_dont_parse_argv(void) { - PyStatus status; - PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitIsolatedConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyPreConfig_InitIsolatedConfig(&preconfig); preconfig.isolated = 0; @@ -899,13 +860,13 @@ static int test_preinit_dont_parse_argv(void) L"-X", L"dev", L"-X", L"utf8", L"script.py"}; - status = Py_PreInitializeFromArgs(&preconfig, Py_ARRAY_LENGTH(argv), argv); + PyStatus status = Py_PreInitializeFromArgs(&preconfig, + Py_ARRAY_LENGTH(argv), argv); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitIsolatedConfig(&config); if (PyStatus_Exception(status)) { @@ -931,7 +892,6 @@ static int test_preinit_parse_argv(void) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -989,12 +949,7 @@ static int check_preinit_isolated_config(int preinit) if (preinit) { PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitIsolatedConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyPreConfig_InitIsolatedConfig(&preconfig); status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { @@ -1007,7 +962,6 @@ static int check_preinit_isolated_config(int preinit) } PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitIsolatedConfig(&config); if (PyStatus_Exception(status)) { @@ -1058,12 +1012,7 @@ static int check_init_python_config(int preinit) if (preinit) { PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitPythonConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyPreConfig_InitPythonConfig(&preconfig); status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { @@ -1072,7 +1021,6 @@ static int check_init_python_config(int preinit) } PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1101,27 +1049,19 @@ static int test_init_python_config(void) static int test_init_dont_configure_locale(void) { - PyStatus status; - PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitPythonConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyPreConfig_InitPythonConfig(&preconfig); preconfig.configure_locale = 0; preconfig.coerce_c_locale = 1; preconfig.coerce_c_locale_warn = 1; - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1140,7 +1080,6 @@ static int test_init_dev_mode(void) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1365,7 +1304,6 @@ static int run_audit_run_test(int argc, wchar_t **argv, void *test) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1415,7 +1353,6 @@ static int test_init_read_set(void) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1465,7 +1402,6 @@ static int test_init_sys_add(void) PySys_AddWarnOption(L"ignore:::sysadd_warnoption"); PyConfig config; - config.struct_size = sizeof(PyConfig); PyStatus status; status = PyConfig_InitPythonConfig(&config); @@ -1533,18 +1469,12 @@ static int test_init_setpath(void) static int test_init_setpath_config(void) { - PyStatus status; PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - - status = PyPreConfig_InitPythonConfig(&preconfig); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyPreConfig_InitPythonConfig(&preconfig); /* Explicitly preinitializes with Python preconfiguration to avoid Py_SetPath() implicit preinitialization with compat preconfiguration. */ - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } @@ -1564,7 +1494,6 @@ static int test_init_setpath_config(void) putenv("TESTPATH="); PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1612,7 +1541,6 @@ static int test_init_warnoptions(void) PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption2"); PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1680,7 +1608,6 @@ static int test_init_run_main(void) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1697,7 +1624,6 @@ static int test_init_main(void) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { @@ -1729,7 +1655,6 @@ static int test_run_main(void) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { diff --git a/Python/frozenmain.c b/Python/frozenmain.c index 76309e9e5da2..c56938ab4899 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -40,7 +40,6 @@ Py_FrozenMain(int argc, char **argv) } PyConfig config; - config.struct_size = sizeof(PyConfig); status = PyConfig_InitPythonConfig(&config); if (PyStatus_Exception(status)) { PyConfig_Clear(&config); diff --git a/Python/initconfig.c b/Python/initconfig.c index dec4bf2e4d57..107429c7ec37 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -529,17 +529,6 @@ Py_GetArgcArgv(int *argc, wchar_t ***argv) : _PyStatus_NO_MEMORY()) -static PyStatus -config_check_struct_size(const PyConfig *config) -{ - if (config->struct_size != sizeof(PyConfig)) { - return _PyStatus_ERR("unsupported PyConfig structure size " - "(Python version mismatch?)"); - } - return _PyStatus_OK(); -} - - /* Free memory allocated in config, but don't clear all attributes */ void PyConfig_Clear(PyConfig *config) @@ -583,15 +572,7 @@ PyConfig_Clear(PyConfig *config) PyStatus _PyConfig_InitCompatConfig(PyConfig *config) { - size_t struct_size = config->struct_size; memset(config, 0, sizeof(*config)); - config->struct_size = struct_size; - - PyStatus status = config_check_struct_size(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } config->_config_init = (int)_PyConfig_INIT_COMPAT; config->isolated = -1; @@ -775,18 +756,6 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) { PyStatus status; - status = config_check_struct_size(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } - - status = config_check_struct_size(config2); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } - PyConfig_Clear(config); #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR @@ -2280,7 +2249,6 @@ core_read_precmdline(PyConfig *config, _PyPreCmdline *precmdline) } PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); status = _PyPreConfig_InitFromPreConfig(&preconfig, &_PyRuntime.preconfig); if (_PyStatus_EXCEPTION(status)) { @@ -2475,12 +2443,6 @@ PyConfig_Read(PyConfig *config) PyStatus status; PyWideStringList orig_argv = _PyWideStringList_INIT; - status = config_check_struct_size(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } - status = _Py_PreInitializeFromConfig(config, NULL); if (_PyStatus_EXCEPTION(status)) { return status; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 6886ab7c42d6..5550194a5d56 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -434,7 +434,6 @@ pathconfig_global_read(_PyPathConfig *pathconfig) { PyStatus status; PyConfig config; - config.struct_size = sizeof(PyConfig); status = _PyConfig_InitCompatConfig(&config); if (_PyStatus_EXCEPTION(status)) { diff --git a/Python/preconfig.c b/Python/preconfig.c index 01c72f5d6bad..89a6227fa672 100644 --- a/Python/preconfig.c +++ b/Python/preconfig.c @@ -269,29 +269,10 @@ _PyPreCmdline_Read(_PyPreCmdline *cmdline, const PyPreConfig *preconfig) /* --- PyPreConfig ----------------------------------------------- */ -static PyStatus -preconfig_check_struct_size(PyPreConfig *config) -{ - if (config->struct_size != sizeof(PyPreConfig)) { - return _PyStatus_ERR("unsupported PyPreConfig structure size " - "(Python version mismatch?)"); - } - return _PyStatus_OK(); -} - - -PyStatus +void _PyPreConfig_InitCompatConfig(PyPreConfig *config) { - size_t struct_size = config->struct_size; memset(config, 0, sizeof(*config)); - config->struct_size = struct_size; - - PyStatus status = preconfig_check_struct_size(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } config->_config_init = (int)_PyConfig_INIT_COMPAT; config->parse_argv = 0; @@ -313,18 +294,13 @@ _PyPreConfig_InitCompatConfig(PyPreConfig *config) #ifdef MS_WINDOWS config->legacy_windows_fs_encoding = -1; #endif - return _PyStatus_OK(); } -PyStatus +void PyPreConfig_InitPythonConfig(PyPreConfig *config) { - PyStatus status = _PyPreConfig_InitCompatConfig(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } + _PyPreConfig_InitCompatConfig(config); config->_config_init = (int)_PyConfig_INIT_PYTHON; config->isolated = 0; @@ -339,18 +315,13 @@ PyPreConfig_InitPythonConfig(PyPreConfig *config) #ifdef MS_WINDOWS config->legacy_windows_fs_encoding = 0; #endif - return _PyStatus_OK(); } -PyStatus +void PyPreConfig_InitIsolatedConfig(PyPreConfig *config) { - PyStatus status = _PyPreConfig_InitCompatConfig(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } + _PyPreConfig_InitCompatConfig(config); config->_config_init = (int)_PyConfig_INIT_ISOLATED; config->configure_locale = 0; @@ -361,7 +332,6 @@ PyPreConfig_InitIsolatedConfig(PyPreConfig *config) #ifdef MS_WINDOWS config->legacy_windows_fs_encoding = 0; #endif - return _PyStatus_OK(); } @@ -369,47 +339,35 @@ PyStatus _PyPreConfig_InitFromPreConfig(PyPreConfig *config, const PyPreConfig *config2) { - PyStatus status = PyPreConfig_InitPythonConfig(config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } - + PyPreConfig_InitPythonConfig(config); preconfig_copy(config, config2); return _PyStatus_OK(); } -PyStatus +void _PyPreConfig_InitFromConfig(PyPreConfig *preconfig, const PyConfig *config) { - PyStatus status; _PyConfigInitEnum config_init = (_PyConfigInitEnum)config->_config_init; switch (config_init) { case _PyConfig_INIT_PYTHON: - status = PyPreConfig_InitPythonConfig(preconfig); + PyPreConfig_InitPythonConfig(preconfig); break; case _PyConfig_INIT_ISOLATED: - status = PyPreConfig_InitIsolatedConfig(preconfig); + PyPreConfig_InitIsolatedConfig(preconfig); break; case _PyConfig_INIT_COMPAT: default: - status = _PyPreConfig_InitCompatConfig(preconfig); - } - - if (_PyStatus_EXCEPTION(status)) { - return status; + _PyPreConfig_InitCompatConfig(preconfig); } _PyPreConfig_GetConfig(preconfig, config); - return _PyStatus_OK(); } static void preconfig_copy(PyPreConfig *config, const PyPreConfig *config2) { - assert(config->struct_size == sizeof(PyPreConfig)); - #define COPY_ATTR(ATTR) config->ATTR = config2->ATTR COPY_ATTR(_config_init); @@ -829,12 +787,6 @@ _PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args) return status; } - status = preconfig_check_struct_size(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } - preconfig_get_global_vars(config); /* Copy LC_CTYPE locale, since it's modified later */ @@ -849,7 +801,6 @@ _PyPreConfig_Read(PyPreConfig *config, const _PyArgv *args) /* Save the config to be able to restore it if encodings change */ PyPreConfig save_config; - save_config.struct_size = sizeof(PyPreConfig); status = _PyPreConfig_InitFromPreConfig(&save_config, config); if (_PyStatus_EXCEPTION(status)) { @@ -976,7 +927,6 @@ PyStatus _PyPreConfig_Write(const PyPreConfig *src_config) { PyPreConfig config; - config.struct_size = sizeof(PyPreConfig); PyStatus status = _PyPreConfig_InitFromPreConfig(&config, src_config); if (_PyStatus_EXCEPTION(status)) { diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index ea0d7a5ee2b9..019c56c3f8b0 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -735,7 +735,6 @@ _Py_PreInitializeFromPyArgv(const PyPreConfig *src_config, const _PyArgv *args) runtime->preinitializing = 1; PyPreConfig config; - config.struct_size = sizeof(PyPreConfig); status = _PyPreConfig_InitFromPreConfig(&config, src_config); if (_PyStatus_EXCEPTION(status)) { @@ -799,12 +798,8 @@ _Py_PreInitializeFromConfig(const PyConfig *config, } PyPreConfig preconfig; - preconfig.struct_size = sizeof(PyPreConfig); - status = _PyPreConfig_InitFromConfig(&preconfig, config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + _PyPreConfig_InitFromConfig(&preconfig, config); if (!config->parse_argv) { return Py_PreInitialize(&preconfig); @@ -852,7 +847,6 @@ pyinit_core(_PyRuntimeState *runtime, } PyConfig config; - config.struct_size = sizeof(PyConfig); status = _PyConfig_InitCompatConfig(&config); if (_PyStatus_EXCEPTION(status)) { @@ -1079,7 +1073,6 @@ Py_InitializeEx(int install_sigs) } PyConfig config; - config.struct_size = sizeof(PyConfig); status = _PyConfig_InitCompatConfig(&config); if (_PyStatus_EXCEPTION(status)) { diff --git a/Python/pystate.c b/Python/pystate.c index 0f0cb2299557..69b86ce4f7a3 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -61,11 +61,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) _PyGC_Initialize(&runtime->gc); _PyEval_Initialize(&runtime->ceval); - runtime->preconfig.struct_size = sizeof(PyPreConfig); - PyStatus status = PyPreConfig_InitPythonConfig(&runtime->preconfig); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + PyPreConfig_InitPythonConfig(&runtime->preconfig); runtime->gilstate.check_enabled = 1; @@ -209,7 +205,6 @@ PyInterpreterState_New(void) memset(interp, 0, sizeof(*interp)); interp->id_refcount = -1; - interp->config.struct_size = sizeof(PyConfig); PyStatus status = PyConfig_InitPythonConfig(&interp->config); if (_PyStatus_EXCEPTION(status)) { /* Don't report status to caller: PyConfig_InitPythonConfig() From webhook-mailer at python.org Tue Oct 1 06:06:20 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 01 Oct 2019 10:06:20 -0000 Subject: [Python-checkins] bpo-38304: PyConfig_InitPythonConfig() cannot fail anymore (GH-16509) Message-ID: https://github.com/python/cpython/commit/8462a4936b3a551dc546a6adea04a70b0a07ca67 commit: 8462a4936b3a551dc546a6adea04a70b0a07ca67 branch: master author: Victor Stinner committer: GitHub date: 2019-10-01T12:06:16+02:00 summary: bpo-38304: PyConfig_InitPythonConfig() cannot fail anymore (GH-16509) PyConfig_InitPythonConfig() and PyConfig_InitIsolatedConfig() no longer return PyStatus: they cannot fail anymore. files: M Doc/c-api/init_config.rst M Include/cpython/initconfig.h M Include/internal/pycore_initconfig.h M Modules/main.c M PC/python_uwp.cpp M Programs/_freeze_importlib.c M Programs/_testembed.c M Python/frozenmain.c M Python/initconfig.c M Python/pathconfig.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 15b8b94d5a74..5e18300471d4 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -343,12 +343,12 @@ PyConfig Structure methods: - .. c:function:: PyStatus PyConfig_InitPythonConfig(PyConfig *config) + .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config) Initialize configuration with :ref:`Python Configuration `. - .. c:function:: PyStatus PyConfig_InitIsolatedConfig(PyConfig *config) + .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config) Initialize configuration with :ref:`Isolated Configuration `. @@ -724,12 +724,9 @@ Example setting the program name:: void init_python(void) { PyStatus status; - PyConfig config; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail; - } + PyConfig config; + PyConfig_InitPythonConfig(&config); /* Set the program name. Implicitly preinitialize Python. */ status = PyConfig_SetString(&config, &config.program_name, @@ -756,12 +753,9 @@ configuration, and then override some parameters:: PyStatus init_python(const char *program_name) { PyStatus status; - PyConfig config; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto done; - } + PyConfig config; + PyConfig_InitPythonConfig(&config); /* Set the program name before reading the configuraton (decode byte string from the locale encoding). @@ -843,13 +837,9 @@ Example of customized Python always running in isolated mode:: int main(int argc, char **argv) { PyStatus status; - PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail; - } + PyConfig config; + PyConfig_InitPythonConfig(&config); config.isolated = 1; /* Decode command line arguments. @@ -1034,14 +1024,9 @@ phases:: void init_python(void) { PyStatus status; - PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig config; + PyConfig_InitPythonConfig(&config); config._init_main = 0; /* ... customize 'config' configuration ... */ diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 25e02cea10dc..4b5ceafe02db 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -404,8 +404,8 @@ typedef struct { int _init_main; } PyConfig; -PyAPI_FUNC(PyStatus) PyConfig_InitPythonConfig(PyConfig *config); -PyAPI_FUNC(PyStatus) PyConfig_InitIsolatedConfig(PyConfig *config); +PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); +PyAPI_FUNC(void) PyConfig_InitIsolatedConfig(PyConfig *config); PyAPI_FUNC(void) PyConfig_Clear(PyConfig *); PyAPI_FUNC(PyStatus) PyConfig_SetString( PyConfig *config, diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index e9810bcf90a8..40831c44b2fa 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -144,7 +144,7 @@ typedef enum { _PyConfig_INIT_ISOLATED = 3 } _PyConfigInitEnum; -PyAPI_FUNC(PyStatus) _PyConfig_InitCompatConfig(PyConfig *config); +PyAPI_FUNC(void) _PyConfig_InitCompatConfig(PyConfig *config); extern PyStatus _PyConfig_Copy( PyConfig *config, const PyConfig *config2); diff --git a/Modules/main.c b/Modules/main.c index 9cbf3ac7060b..526b0ade84a4 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -61,11 +61,7 @@ pymain_init(const _PyArgv *args) } PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + PyConfig_InitPythonConfig(&config); /* pass NULL as the config: config is read from command line arguments, environment variables, configuration files */ diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp index 758c8f73725e..88369e8fbfeb 100644 --- a/PC/python_uwp.cpp +++ b/PC/python_uwp.cpp @@ -193,10 +193,7 @@ wmain(int argc, wchar_t **argv) } } - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail_without_config; - } + PyConfig_InitPythonConfig(&config); status = PyConfig_SetArgv(&config, argc, argv); if (PyStatus_Exception(status)) { diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 74735f279c58..2e4ccbb154a4 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -76,17 +76,12 @@ main(int argc, char *argv[]) } text[text_size] = '\0'; - PyStatus status; PyConfig config; - - status = PyConfig_InitIsolatedConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitIsolatedConfig(&config); config.site_import = 0; + PyStatus status; status = PyConfig_SetString(&config, &config.program_name, L"./_freeze_importlib"); if (PyStatus_Exception(status)) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index d2d4c7f8c651..b98a38a1ba67 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -394,11 +394,7 @@ static int check_init_compat_config(int preinit) } PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyConfig_InitCompatConfig(&config); config_set_program_name(&config); init_from_config_clear(&config); @@ -488,11 +484,8 @@ static int test_init_from_config(void) } PyConfig config; + _PyConfig_InitCompatConfig(&config); - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config.install_signal_handlers = 0; /* FIXME: test use_environment */ @@ -621,14 +614,8 @@ static int test_init_from_config(void) static int check_init_parse_argv(int parse_argv) { - PyStatus status; - PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config.parse_argv = parse_argv; @@ -705,16 +692,10 @@ static int test_init_compat_env(void) static int test_init_python_env(void) { - PyStatus status; - set_all_env_vars(); PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config_set_program_name(&config); init_from_config_clear(&config); @@ -760,15 +741,9 @@ static int test_init_env_dev_mode_alloc(void) static int test_init_isolated_flag(void) { - PyStatus status; - /* Test PyConfig.isolated=1 */ PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); Py_IsolatedFlag = 0; config.isolated = 1; @@ -797,11 +772,8 @@ static int test_preinit_isolated1(void) } PyConfig config; + _PyConfig_InitCompatConfig(&config); - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_program_name(&config); set_all_env_vars(); init_from_config_clear(&config); @@ -827,11 +799,7 @@ static int test_preinit_isolated2(void) /* Test PyConfig.isolated=1 */ PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyConfig_InitCompatConfig(&config); Py_IsolatedFlag = 0; config.isolated = 1; @@ -867,12 +835,7 @@ static int test_preinit_dont_parse_argv(void) } PyConfig config; - - status = PyConfig_InitIsolatedConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitIsolatedConfig(&config); config.isolated = 0; @@ -890,14 +853,8 @@ static int test_preinit_dont_parse_argv(void) static int test_preinit_parse_argv(void) { - PyStatus status; PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); /* Pre-initialize implicitly using argv: make sure that -X dev is used to configure the allocation in preinitialization */ @@ -962,12 +919,8 @@ static int check_preinit_isolated_config(int preinit) } PyConfig config; + PyConfig_InitIsolatedConfig(&config); - status = PyConfig_InitIsolatedConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } config_set_program_name(&config); init_from_config_clear(&config); @@ -995,8 +948,6 @@ static int test_init_isolated_config(void) static int check_init_python_config(int preinit) { - PyStatus status; - /* global configuration variables must be ignored */ set_all_global_config_variables(); Py_IsolatedFlag = 1; @@ -1014,18 +965,15 @@ static int check_init_python_config(int preinit) PyPreConfig preconfig; PyPreConfig_InitPythonConfig(&preconfig); - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } } PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_program_name(&config); init_from_config_clear(&config); @@ -1062,11 +1010,8 @@ static int test_init_dont_configure_locale(void) } PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_program_name(&config); init_from_config_clear(&config); @@ -1078,13 +1023,9 @@ static int test_init_dont_configure_locale(void) static int test_init_dev_mode(void) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } putenv("PYTHONFAULTHANDLER="); putenv("PYTHONMALLOC="); config.dev_mode = 1; @@ -1302,13 +1243,9 @@ static int test_audit_run_file(void) static int run_audit_run_test(int argc, wchar_t **argv, void *test) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config.argv.length = argc; config.argv.items = argv; config.parse_argv = 1; @@ -1320,7 +1257,7 @@ static int run_audit_run_test(int argc, wchar_t **argv, void *test) PySys_AddAuditHook(_audit_hook_run, test); - status = Py_InitializeFromConfig(&config); + PyStatus status = Py_InitializeFromConfig(&config); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } @@ -1353,11 +1290,7 @@ static int test_init_read_set(void) { PyStatus status; PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); status = PyConfig_SetBytesString(&config, &config.program_name, "./init_read_set"); @@ -1402,12 +1335,7 @@ static int test_init_sys_add(void) PySys_AddWarnOption(L"ignore:::sysadd_warnoption"); PyConfig config; - - PyStatus status; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail; - } + PyConfig_InitPythonConfig(&config); wchar_t* argv[] = { L"python3", @@ -1419,6 +1347,7 @@ static int test_init_sys_add(void) config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); config.parse_argv = 1; + PyStatus status; status = PyWideStringList_Append(&config.xoptions, L"config_xoption"); if (PyStatus_Exception(status)) { @@ -1494,11 +1423,8 @@ static int test_init_setpath_config(void) putenv("TESTPATH="); PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_string(&config, &config.program_name, L"conf_program_name"); config_set_string(&config, &config.executable, L"conf_executable"); init_from_config_clear(&config); @@ -1534,24 +1460,20 @@ static int test_init_setpythonhome(void) static int test_init_warnoptions(void) { - PyStatus status; putenv("PYTHONWARNINGS=ignore:::env1,ignore:::env2"); PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption1"); PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption2"); PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config.dev_mode = 1; config.bytes_warning = 1; config_set_program_name(&config); + PyStatus status; status = PyWideStringList_Append(&config.warnoptions, L"ignore:::PyConfig_BeforeRead"); if (PyStatus_Exception(status)) { @@ -1606,13 +1528,9 @@ static void configure_init_main(PyConfig *config) static int test_init_run_main(void) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } configure_init_main(&config); init_from_config_clear(&config); @@ -1622,13 +1540,9 @@ static int test_init_run_main(void) static int test_init_main(void) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } configure_init_main(&config); config._init_main = 0; init_from_config_clear(&config); @@ -1642,7 +1556,7 @@ static int test_init_main(void) exit(1); } - status = _Py_InitializeMain(); + PyStatus status = _Py_InitializeMain(); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } @@ -1653,14 +1567,8 @@ static int test_init_main(void) static int test_run_main(void) { - PyStatus status; PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); wchar_t *argv[] = {L"python3", L"-c", (L"import sys; " diff --git a/Python/frozenmain.c b/Python/frozenmain.c index c56938ab4899..7f9cc1931736 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -40,11 +40,7 @@ Py_FrozenMain(int argc, char **argv) } PyConfig config; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */ if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') diff --git a/Python/initconfig.c b/Python/initconfig.c index 107429c7ec37..caa9bf5f5689 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -569,7 +569,7 @@ PyConfig_Clear(PyConfig *config) } -PyStatus +void _PyConfig_InitCompatConfig(PyConfig *config) { memset(config, 0, sizeof(*config)); @@ -603,17 +603,13 @@ _PyConfig_InitCompatConfig(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = -1; #endif - return _PyStatus_OK(); } -static PyStatus +static void config_init_defaults(PyConfig *config) { - PyStatus status = _PyConfig_InitCompatConfig(config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + _PyConfig_InitCompatConfig(config); config->isolated = 0; config->use_environment = 1; @@ -632,35 +628,24 @@ config_init_defaults(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = 0; #endif - return _PyStatus_OK(); } -PyStatus +void PyConfig_InitPythonConfig(PyConfig *config) { - PyStatus status = config_init_defaults(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } + config_init_defaults(config); config->_config_init = (int)_PyConfig_INIT_PYTHON; config->configure_c_stdio = 1; config->parse_argv = 1; - - return _PyStatus_OK(); } -PyStatus +void PyConfig_InitIsolatedConfig(PyConfig *config) { - PyStatus status = config_init_defaults(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } + config_init_defaults(config); config->_config_init = (int)_PyConfig_INIT_ISOLATED; config->isolated = 1; @@ -675,8 +660,6 @@ PyConfig_InitIsolatedConfig(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = 0; #endif - - return _PyStatus_OK(); } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index 5550194a5d56..61408e19e3a7 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -432,16 +432,11 @@ _PyConfig_InitPathConfig(PyConfig *config) static PyStatus pathconfig_global_read(_PyPathConfig *pathconfig) { - PyStatus status; PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + _PyConfig_InitCompatConfig(&config); /* Call _PyConfig_InitPathConfig() */ - status = PyConfig_Read(&config); + PyStatus status = PyConfig_Read(&config); if (_PyStatus_EXCEPTION(status)) { goto done; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 019c56c3f8b0..add7519ed0f7 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -847,11 +847,7 @@ pyinit_core(_PyRuntimeState *runtime, } PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + _PyConfig_InitCompatConfig(&config); status = _PyConfig_Copy(&config, src_config); if (_PyStatus_EXCEPTION(status)) { @@ -1073,11 +1069,7 @@ Py_InitializeEx(int install_sigs) } PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - Py_ExitStatusException(status); - } + _PyConfig_InitCompatConfig(&config); config.install_signal_handlers = install_sigs; diff --git a/Python/pystate.c b/Python/pystate.c index 69b86ce4f7a3..f3d89e7d2b25 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -205,14 +205,7 @@ PyInterpreterState_New(void) memset(interp, 0, sizeof(*interp)); interp->id_refcount = -1; - PyStatus status = PyConfig_InitPythonConfig(&interp->config); - if (_PyStatus_EXCEPTION(status)) { - /* Don't report status to caller: PyConfig_InitPythonConfig() - can only fail with a memory allocation error. */ - PyConfig_Clear(&interp->config); - PyMem_RawFree(interp); - return NULL; - } + PyConfig_InitPythonConfig(&interp->config); interp->eval_frame = _PyEval_EvalFrameDefault; #ifdef HAVE_DLOPEN From webhook-mailer at python.org Tue Oct 1 06:26:08 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 01 Oct 2019 10:26:08 -0000 Subject: [Python-checkins] bpo-38304: PyConfig_InitPythonConfig() cannot fail anymore (GH-16509) Message-ID: https://github.com/python/cpython/commit/d49f096cc41f57155efe71cd089c29b38c218488 commit: d49f096cc41f57155efe71cd089c29b38c218488 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-10-01T03:26:04-07:00 summary: bpo-38304: PyConfig_InitPythonConfig() cannot fail anymore (GH-16509) PyConfig_InitPythonConfig() and PyConfig_InitIsolatedConfig() no longer return PyStatus: they cannot fail anymore. (cherry picked from commit 8462a4936b3a551dc546a6adea04a70b0a07ca67) Co-authored-by: Victor Stinner files: M Doc/c-api/init_config.rst M Include/cpython/initconfig.h M Include/internal/pycore_initconfig.h M Modules/main.c M PC/python_uwp.cpp M Programs/_freeze_importlib.c M Programs/_testembed.c M Python/frozenmain.c M Python/initconfig.c M Python/pathconfig.c M Python/pylifecycle.c M Python/pystate.c diff --git a/Doc/c-api/init_config.rst b/Doc/c-api/init_config.rst index 15b8b94d5a749..5e18300471d46 100644 --- a/Doc/c-api/init_config.rst +++ b/Doc/c-api/init_config.rst @@ -343,12 +343,12 @@ PyConfig Structure methods: - .. c:function:: PyStatus PyConfig_InitPythonConfig(PyConfig *config) + .. c:function:: void PyConfig_InitPythonConfig(PyConfig *config) Initialize configuration with :ref:`Python Configuration `. - .. c:function:: PyStatus PyConfig_InitIsolatedConfig(PyConfig *config) + .. c:function:: void PyConfig_InitIsolatedConfig(PyConfig *config) Initialize configuration with :ref:`Isolated Configuration `. @@ -724,12 +724,9 @@ Example setting the program name:: void init_python(void) { PyStatus status; - PyConfig config; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail; - } + PyConfig config; + PyConfig_InitPythonConfig(&config); /* Set the program name. Implicitly preinitialize Python. */ status = PyConfig_SetString(&config, &config.program_name, @@ -756,12 +753,9 @@ configuration, and then override some parameters:: PyStatus init_python(const char *program_name) { PyStatus status; - PyConfig config; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto done; - } + PyConfig config; + PyConfig_InitPythonConfig(&config); /* Set the program name before reading the configuraton (decode byte string from the locale encoding). @@ -843,13 +837,9 @@ Example of customized Python always running in isolated mode:: int main(int argc, char **argv) { PyStatus status; - PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail; - } + PyConfig config; + PyConfig_InitPythonConfig(&config); config.isolated = 1; /* Decode command line arguments. @@ -1034,14 +1024,9 @@ phases:: void init_python(void) { PyStatus status; - PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig config; + PyConfig_InitPythonConfig(&config); config._init_main = 0; /* ... customize 'config' configuration ... */ diff --git a/Include/cpython/initconfig.h b/Include/cpython/initconfig.h index 25e02cea10dc3..4b5ceafe02dbc 100644 --- a/Include/cpython/initconfig.h +++ b/Include/cpython/initconfig.h @@ -404,8 +404,8 @@ typedef struct { int _init_main; } PyConfig; -PyAPI_FUNC(PyStatus) PyConfig_InitPythonConfig(PyConfig *config); -PyAPI_FUNC(PyStatus) PyConfig_InitIsolatedConfig(PyConfig *config); +PyAPI_FUNC(void) PyConfig_InitPythonConfig(PyConfig *config); +PyAPI_FUNC(void) PyConfig_InitIsolatedConfig(PyConfig *config); PyAPI_FUNC(void) PyConfig_Clear(PyConfig *); PyAPI_FUNC(PyStatus) PyConfig_SetString( PyConfig *config, diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index e9810bcf90a85..40831c44b2fa6 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -144,7 +144,7 @@ typedef enum { _PyConfig_INIT_ISOLATED = 3 } _PyConfigInitEnum; -PyAPI_FUNC(PyStatus) _PyConfig_InitCompatConfig(PyConfig *config); +PyAPI_FUNC(void) _PyConfig_InitCompatConfig(PyConfig *config); extern PyStatus _PyConfig_Copy( PyConfig *config, const PyConfig *config2); diff --git a/Modules/main.c b/Modules/main.c index 66af89f561221..2a360b58efa83 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -61,11 +61,7 @@ pymain_init(const _PyArgv *args) } PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + PyConfig_InitPythonConfig(&config); /* pass NULL as the config: config is read from command line arguments, environment variables, configuration files */ diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp index 758c8f73725e7..88369e8fbfeb3 100644 --- a/PC/python_uwp.cpp +++ b/PC/python_uwp.cpp @@ -193,10 +193,7 @@ wmain(int argc, wchar_t **argv) } } - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail_without_config; - } + PyConfig_InitPythonConfig(&config); status = PyConfig_SetArgv(&config, argc, argv); if (PyStatus_Exception(status)) { diff --git a/Programs/_freeze_importlib.c b/Programs/_freeze_importlib.c index 74735f279c585..2e4ccbb154a41 100644 --- a/Programs/_freeze_importlib.c +++ b/Programs/_freeze_importlib.c @@ -76,17 +76,12 @@ main(int argc, char *argv[]) } text[text_size] = '\0'; - PyStatus status; PyConfig config; - - status = PyConfig_InitIsolatedConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitIsolatedConfig(&config); config.site_import = 0; + PyStatus status; status = PyConfig_SetString(&config, &config.program_name, L"./_freeze_importlib"); if (PyStatus_Exception(status)) { diff --git a/Programs/_testembed.c b/Programs/_testembed.c index d2d4c7f8c651c..b98a38a1ba678 100644 --- a/Programs/_testembed.c +++ b/Programs/_testembed.c @@ -394,11 +394,7 @@ static int check_init_compat_config(int preinit) } PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyConfig_InitCompatConfig(&config); config_set_program_name(&config); init_from_config_clear(&config); @@ -488,11 +484,8 @@ static int test_init_from_config(void) } PyConfig config; + _PyConfig_InitCompatConfig(&config); - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config.install_signal_handlers = 0; /* FIXME: test use_environment */ @@ -621,14 +614,8 @@ static int test_init_from_config(void) static int check_init_parse_argv(int parse_argv) { - PyStatus status; - PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config.parse_argv = parse_argv; @@ -705,16 +692,10 @@ static int test_init_compat_env(void) static int test_init_python_env(void) { - PyStatus status; - set_all_env_vars(); PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config_set_program_name(&config); init_from_config_clear(&config); @@ -760,15 +741,9 @@ static int test_init_env_dev_mode_alloc(void) static int test_init_isolated_flag(void) { - PyStatus status; - /* Test PyConfig.isolated=1 */ PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); Py_IsolatedFlag = 0; config.isolated = 1; @@ -797,11 +772,8 @@ static int test_preinit_isolated1(void) } PyConfig config; + _PyConfig_InitCompatConfig(&config); - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_program_name(&config); set_all_env_vars(); init_from_config_clear(&config); @@ -827,11 +799,7 @@ static int test_preinit_isolated2(void) /* Test PyConfig.isolated=1 */ PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + _PyConfig_InitCompatConfig(&config); Py_IsolatedFlag = 0; config.isolated = 1; @@ -867,12 +835,7 @@ static int test_preinit_dont_parse_argv(void) } PyConfig config; - - status = PyConfig_InitIsolatedConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitIsolatedConfig(&config); config.isolated = 0; @@ -890,14 +853,8 @@ static int test_preinit_dont_parse_argv(void) static int test_preinit_parse_argv(void) { - PyStatus status; PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); /* Pre-initialize implicitly using argv: make sure that -X dev is used to configure the allocation in preinitialization */ @@ -962,12 +919,8 @@ static int check_preinit_isolated_config(int preinit) } PyConfig config; + PyConfig_InitIsolatedConfig(&config); - status = PyConfig_InitIsolatedConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } config_set_program_name(&config); init_from_config_clear(&config); @@ -995,8 +948,6 @@ static int test_init_isolated_config(void) static int check_init_python_config(int preinit) { - PyStatus status; - /* global configuration variables must be ignored */ set_all_global_config_variables(); Py_IsolatedFlag = 1; @@ -1014,18 +965,15 @@ static int check_init_python_config(int preinit) PyPreConfig preconfig; PyPreConfig_InitPythonConfig(&preconfig); - status = Py_PreInitialize(&preconfig); + PyStatus status = Py_PreInitialize(&preconfig); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } } PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_program_name(&config); init_from_config_clear(&config); @@ -1062,11 +1010,8 @@ static int test_init_dont_configure_locale(void) } PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_program_name(&config); init_from_config_clear(&config); @@ -1078,13 +1023,9 @@ static int test_init_dont_configure_locale(void) static int test_init_dev_mode(void) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } putenv("PYTHONFAULTHANDLER="); putenv("PYTHONMALLOC="); config.dev_mode = 1; @@ -1302,13 +1243,9 @@ static int test_audit_run_file(void) static int run_audit_run_test(int argc, wchar_t **argv, void *test) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config.argv.length = argc; config.argv.items = argv; config.parse_argv = 1; @@ -1320,7 +1257,7 @@ static int run_audit_run_test(int argc, wchar_t **argv, void *test) PySys_AddAuditHook(_audit_hook_run, test); - status = Py_InitializeFromConfig(&config); + PyStatus status = Py_InitializeFromConfig(&config); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } @@ -1353,11 +1290,7 @@ static int test_init_read_set(void) { PyStatus status; PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); status = PyConfig_SetBytesString(&config, &config.program_name, "./init_read_set"); @@ -1402,12 +1335,7 @@ static int test_init_sys_add(void) PySys_AddWarnOption(L"ignore:::sysadd_warnoption"); PyConfig config; - - PyStatus status; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - goto fail; - } + PyConfig_InitPythonConfig(&config); wchar_t* argv[] = { L"python3", @@ -1419,6 +1347,7 @@ static int test_init_sys_add(void) config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv); config.parse_argv = 1; + PyStatus status; status = PyWideStringList_Append(&config.xoptions, L"config_xoption"); if (PyStatus_Exception(status)) { @@ -1494,11 +1423,8 @@ static int test_init_setpath_config(void) putenv("TESTPATH="); PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } config_set_string(&config, &config.program_name, L"conf_program_name"); config_set_string(&config, &config.executable, L"conf_executable"); init_from_config_clear(&config); @@ -1534,24 +1460,20 @@ static int test_init_setpythonhome(void) static int test_init_warnoptions(void) { - PyStatus status; putenv("PYTHONWARNINGS=ignore:::env1,ignore:::env2"); PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption1"); PySys_AddWarnOption(L"ignore:::PySys_AddWarnOption2"); PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config.dev_mode = 1; config.bytes_warning = 1; config_set_program_name(&config); + PyStatus status; status = PyWideStringList_Append(&config.warnoptions, L"ignore:::PyConfig_BeforeRead"); if (PyStatus_Exception(status)) { @@ -1606,13 +1528,9 @@ static void configure_init_main(PyConfig *config) static int test_init_run_main(void) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } configure_init_main(&config); init_from_config_clear(&config); @@ -1622,13 +1540,9 @@ static int test_init_run_main(void) static int test_init_main(void) { - PyStatus status; PyConfig config; + PyConfig_InitPythonConfig(&config); - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - Py_ExitStatusException(status); - } configure_init_main(&config); config._init_main = 0; init_from_config_clear(&config); @@ -1642,7 +1556,7 @@ static int test_init_main(void) exit(1); } - status = _Py_InitializeMain(); + PyStatus status = _Py_InitializeMain(); if (PyStatus_Exception(status)) { Py_ExitStatusException(status); } @@ -1653,14 +1567,8 @@ static int test_init_main(void) static int test_run_main(void) { - PyStatus status; PyConfig config; - - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); wchar_t *argv[] = {L"python3", L"-c", (L"import sys; " diff --git a/Python/frozenmain.c b/Python/frozenmain.c index c56938ab48994..7f9cc19317360 100644 --- a/Python/frozenmain.c +++ b/Python/frozenmain.c @@ -40,11 +40,7 @@ Py_FrozenMain(int argc, char **argv) } PyConfig config; - status = PyConfig_InitPythonConfig(&config); - if (PyStatus_Exception(status)) { - PyConfig_Clear(&config); - Py_ExitStatusException(status); - } + PyConfig_InitPythonConfig(&config); config.pathconfig_warnings = 0; /* Suppress errors from getpath.c */ if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\0') diff --git a/Python/initconfig.c b/Python/initconfig.c index 9164c7cfc8e85..a41a3292d3e2c 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -569,7 +569,7 @@ PyConfig_Clear(PyConfig *config) } -PyStatus +void _PyConfig_InitCompatConfig(PyConfig *config) { memset(config, 0, sizeof(*config)); @@ -603,17 +603,13 @@ _PyConfig_InitCompatConfig(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = -1; #endif - return _PyStatus_OK(); } -static PyStatus +static void config_init_defaults(PyConfig *config) { - PyStatus status = _PyConfig_InitCompatConfig(config); - if (_PyStatus_EXCEPTION(status)) { - return status; - } + _PyConfig_InitCompatConfig(config); config->isolated = 0; config->use_environment = 1; @@ -632,35 +628,24 @@ config_init_defaults(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = 0; #endif - return _PyStatus_OK(); } -PyStatus +void PyConfig_InitPythonConfig(PyConfig *config) { - PyStatus status = config_init_defaults(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } + config_init_defaults(config); config->_config_init = (int)_PyConfig_INIT_PYTHON; config->configure_c_stdio = 1; config->parse_argv = 1; - - return _PyStatus_OK(); } -PyStatus +void PyConfig_InitIsolatedConfig(PyConfig *config) { - PyStatus status = config_init_defaults(config); - if (_PyStatus_EXCEPTION(status)) { - _PyStatus_UPDATE_FUNC(status); - return status; - } + config_init_defaults(config); config->_config_init = (int)_PyConfig_INIT_ISOLATED; config->isolated = 1; @@ -675,8 +660,6 @@ PyConfig_InitIsolatedConfig(PyConfig *config) #ifdef MS_WINDOWS config->legacy_windows_stdio = 0; #endif - - return _PyStatus_OK(); } diff --git a/Python/pathconfig.c b/Python/pathconfig.c index ff4bbf2a97ebe..7f3fdcc103f7b 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -432,16 +432,11 @@ _PyConfig_InitPathConfig(PyConfig *config) static PyStatus pathconfig_global_read(_PyPathConfig *pathconfig) { - PyStatus status; PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + _PyConfig_InitCompatConfig(&config); /* Call _PyConfig_InitPathConfig() */ - status = PyConfig_Read(&config); + PyStatus status = PyConfig_Read(&config); if (_PyStatus_EXCEPTION(status)) { goto done; } diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 5174f749c68d6..feb9285239240 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -843,11 +843,7 @@ pyinit_core(_PyRuntimeState *runtime, } PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + _PyConfig_InitCompatConfig(&config); status = _PyConfig_Copy(&config, src_config); if (_PyStatus_EXCEPTION(status)) { @@ -1070,11 +1066,7 @@ Py_InitializeEx(int install_sigs) } PyConfig config; - - status = _PyConfig_InitCompatConfig(&config); - if (_PyStatus_EXCEPTION(status)) { - Py_ExitStatusException(status); - } + _PyConfig_InitCompatConfig(&config); config.install_signal_handlers = install_sigs; diff --git a/Python/pystate.c b/Python/pystate.c index 098280d76dfc0..aba673c00a432 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -206,14 +206,7 @@ PyInterpreterState_New(void) interp->id_refcount = -1; interp->check_interval = 100; - PyStatus status = PyConfig_InitPythonConfig(&interp->config); - if (_PyStatus_EXCEPTION(status)) { - /* Don't report status to caller: PyConfig_InitPythonConfig() - can only fail with a memory allocation error. */ - PyConfig_Clear(&interp->config); - PyMem_RawFree(interp); - return NULL; - } + PyConfig_InitPythonConfig(&interp->config); interp->eval_frame = _PyEval_EvalFrameDefault; #ifdef HAVE_DLOPEN From webhook-mailer at python.org Tue Oct 1 06:29:40 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 01 Oct 2019 10:29:40 -0000 Subject: [Python-checkins] bpo-36670: Multiple regrtest bugfixes (GH-16511) Message-ID: https://github.com/python/cpython/commit/982bfa4da07b2e5749a0f4e68f99e972bcc3a549 commit: 982bfa4da07b2e5749a0f4e68f99e972bcc3a549 branch: master author: Victor Stinner committer: GitHub date: 2019-10-01T12:29:36+02:00 summary: bpo-36670: Multiple regrtest bugfixes (GH-16511) * Windows: Fix counter name in WindowsLoadTracker. Counter names are localized: use the registry to get the counter name. Original change written by Lorenz Mende. * Regrtest.main() now ensures that the Windows load tracker is also killed if an exception is raised * TestWorkerProcess now ensures that worker processes are no longer running before exiting: kill also worker processes when an exception is raised. * Enhance regrtest messages and warnings: include test name, duration, add a worker identifier, etc. * Rename MultiprocessRunner to TestWorkerProcess * Use print_warning() to display warnings. Co-Authored-By: Lorenz Mende files: M Lib/test/libregrtest/main.py M Lib/test/libregrtest/runtest_mp.py M Lib/test/libregrtest/win_utils.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 299700686928f..fd701c452ceb5 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -508,10 +508,6 @@ def run_tests(self): self.run_tests_sequential() def finalize(self): - if self.win_load_tracker is not None: - self.win_load_tracker.close() - self.win_load_tracker = None - if self.next_single_filename: if self.next_single_test: with open(self.next_single_filename, 'w') as fp: @@ -680,11 +676,16 @@ def _main(self, tests, kwargs): # typeperf.exe for x64, x86 or ARM print(f'Failed to create WindowsLoadTracker: {error}') - self.run_tests() - self.display_result() - - if self.ns.verbose2 and self.bad: - self.rerun_failed_tests() + try: + self.run_tests() + self.display_result() + + if self.ns.verbose2 and self.bad: + self.rerun_failed_tests() + finally: + if self.win_load_tracker is not None: + self.win_load_tracker.close() + self.win_load_tracker = None self.finalize() diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 9cb5be6bb8ae8..38b05781de5fc 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -15,7 +15,7 @@ runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, format_test_result, TestResult, is_failed, TIMEOUT) from test.libregrtest.setup import setup_tests -from test.libregrtest.utils import format_duration +from test.libregrtest.utils import format_duration, print_warning # Display the running tests if nothing happened last N seconds @@ -103,9 +103,10 @@ class ExitThread(Exception): pass -class MultiprocessThread(threading.Thread): - def __init__(self, pending, output, ns, timeout): +class TestWorkerProcess(threading.Thread): + def __init__(self, worker_id, pending, output, ns, timeout): super().__init__() + self.worker_id = worker_id self.pending = pending self.output = output self.ns = ns @@ -114,12 +115,16 @@ def __init__(self, pending, output, ns, timeout): self.start_time = None self._popen = None self._killed = False + self._stopped = False def __repr__(self): - info = ['MultiprocessThread'] - test = self.current_test_name + info = [f'TestWorkerProcess #{self.worker_id}'] if self.is_alive(): - info.append('alive') + dt = time.monotonic() - self.start_time + info.append("running for %s" % format_duration(dt)) + else: + info.append('stopped') + test = self.current_test_name if test: info.append(f'test={test}') popen = self._popen @@ -128,53 +133,24 @@ def __repr__(self): return '<%s>' % ' '.join(info) def _kill(self): - dt = time.monotonic() - self.start_time + if self._killed: + return + self._killed = True popen = self._popen - pid = popen.pid - print("Kill worker process %s running for %.1f sec" % (pid, dt), - file=sys.stderr, flush=True) + if popen is None: + return + print(f"Kill {self}", file=sys.stderr, flush=True) try: popen.kill() - return True except OSError as exc: - print("WARNING: Failed to kill worker process %s: %r" % (pid, exc), - file=sys.stderr, flush=True) - return False - - def _close_wait(self): - popen = self._popen - - # stdout and stderr must be closed to ensure that communicate() - # does not hang - popen.stdout.close() - popen.stderr.close() - - try: - popen.wait(JOIN_TIMEOUT) - except (subprocess.TimeoutExpired, OSError) as exc: - print("WARNING: Failed to wait for worker process %s " - "completion (timeout=%.1f sec): %r" - % (popen.pid, JOIN_TIMEOUT, exc), - file=sys.stderr, flush=True) - - def kill(self): - """ - Kill the current process (if any). - - This method can be called by the thread running the process, - or by another thread. - """ - self._killed = True - - if self._popen is None: - return - - if not self._kill(): - return + print_warning(f"Failed to kill {self}: {exc!r}") - self._close_wait() + def stop(self): + # Method called from a different thread to stop this thread + self._stopped = True + self._kill() def mp_result_error(self, test_name, error_type, stdout='', stderr='', err_msg=None): @@ -190,59 +166,69 @@ def _timedout(self, test_name): try: stdout, stderr = popen.communicate(timeout=JOIN_TIMEOUT) except (subprocess.TimeoutExpired, OSError) as exc: - print("WARNING: Failed to read worker process %s output " - "(timeout=%.1f sec): %r" - % (popen.pid, JOIN_TIMEOUT, exc), - file=sys.stderr, flush=True) - - self._close_wait() + print_warning(f"Failed to read {self} output " + f"(timeout={format_duration(JOIN_TIMEOUT)}): " + f"{exc!r}") return self.mp_result_error(test_name, TIMEOUT, stdout, stderr) - def _runtest(self, test_name): - try: - self.start_time = time.monotonic() - self.current_test_name = test_name + def _run_process(self, test_name): + self.start_time = time.monotonic() + self.current_test_name = test_name + try: + self._killed = False self._popen = run_test_in_subprocess(test_name, self.ns) popen = self._popen + except: + self.current_test_name = None + raise + + try: + if self._stopped: + # If kill() has been called before self._popen is set, + # self._popen is still running. Call again kill() + # to ensure that the process is killed. + self._kill() + raise ExitThread + try: - try: - if self._killed: - # If kill() has been called before self._popen is set, - # self._popen is still running. Call again kill() - # to ensure that the process is killed. - self.kill() - raise ExitThread - - try: - stdout, stderr = popen.communicate(timeout=self.timeout) - except subprocess.TimeoutExpired: - if self._killed: - # kill() has been called: communicate() fails - # on reading closed stdout/stderr - raise ExitThread - - return self._timedout(test_name) - except OSError: - if self._killed: - # kill() has been called: communicate() fails - # on reading closed stdout/stderr - raise ExitThread - raise - except: - self.kill() - raise - finally: - self._close_wait() + stdout, stderr = popen.communicate(timeout=self.timeout) + except subprocess.TimeoutExpired: + if self._stopped: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + + return self._timedout(test_name) + except OSError: + if self._stopped: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + raise retcode = popen.returncode + stdout = stdout.strip() + stderr = stderr.rstrip() + + return (retcode, stdout, stderr) + except: + self._kill() + raise finally: - self.current_test_name = None + self._wait_completed() self._popen = None + self.current_test_name = None + + def _runtest(self, test_name): + result = self._run_process(test_name) - stdout = stdout.strip() - stderr = stderr.rstrip() + if isinstance(result, MultiprocessResult): + # _timedout() case + return result + + retcode, stdout, stderr = result err_msg = None if retcode != 0: @@ -266,7 +252,7 @@ def _runtest(self, test_name): return MultiprocessResult(result, stdout, stderr, err_msg) def run(self): - while not self._killed: + while not self._stopped: try: try: test_name = next(self.pending) @@ -284,6 +270,33 @@ def run(self): self.output.put((True, traceback.format_exc())) break + def _wait_completed(self): + popen = self._popen + + # stdout and stderr must be closed to ensure that communicate() + # does not hang + popen.stdout.close() + popen.stderr.close() + + try: + popen.wait(JOIN_TIMEOUT) + except (subprocess.TimeoutExpired, OSError) as exc: + print_warning(f"Failed to wait for {self} completion " + f"(timeout={format_duration(JOIN_TIMEOUT)}): " + f"{exc!r}") + + def wait_stopped(self, start_time): + while True: + # Write a message every second + self.join(1.0) + if not self.is_alive(): + break + dt = time.monotonic() - start_time + print(f"Waiting for {self} thread for {format_duration(dt)}", flush=True) + if dt > JOIN_TIMEOUT: + print_warning(f"Failed to join {self} in {format_duration(dt)}") + break + def get_running(workers): running = [] @@ -298,7 +311,7 @@ def get_running(workers): return running -class MultiprocessRunner: +class MultiprocessTestRunner: def __init__(self, regrtest): self.regrtest = regrtest self.ns = regrtest.ns @@ -311,30 +324,20 @@ def __init__(self, regrtest): self.workers = None def start_workers(self): - self.workers = [MultiprocessThread(self.pending, self.output, - self.ns, self.worker_timeout) - for _ in range(self.ns.use_mp)] + self.workers = [TestWorkerProcess(index, self.pending, self.output, + self.ns, self.worker_timeout) + for index in range(1, self.ns.use_mp + 1)] print("Run tests in parallel using %s child processes" % len(self.workers)) for worker in self.workers: worker.start() - def wait_workers(self): + def stop_workers(self): start_time = time.monotonic() for worker in self.workers: - worker.kill() + worker.stop() for worker in self.workers: - while True: - worker.join(1.0) - if not worker.is_alive(): - break - dt = time.monotonic() - start_time - print("Wait for regrtest worker %r for %.1f sec" % (worker, dt), - flush=True) - if dt > JOIN_TIMEOUT: - print("Warning -- failed to join a regrtest worker %s" - % worker, flush=True) - break + worker.wait_stopped(start_time) def _get_result(self): if not any(worker.is_alive() for worker in self.workers): @@ -418,10 +421,11 @@ def run_tests(self): if self.ns.timeout is not None: faulthandler.cancel_dump_traceback_later() - # a test failed (and --failfast is set) or all tests completed - self.pending.stop() - self.wait_workers() + # Always ensure that all worker processes are no longer + # worker when we exit this function + self.pending.stop() + self.stop_workers() def run_tests_multiprocess(regrtest): - MultiprocessRunner(regrtest).run_tests() + MultiprocessTestRunner(regrtest).run_tests() diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index ec2d6c663e83f..f0c17b906f519 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -3,16 +3,22 @@ import os import subprocess import uuid +import winreg from test import support +from test.libregrtest.utils import print_warning # Max size of asynchronous reads BUFSIZE = 8192 # Exponential damping factor (see below) LOAD_FACTOR_1 = 0.9200444146293232478931553241 + # Seconds per measurement SAMPLING_INTERVAL = 5 -COUNTER_NAME = r'\System\Processor Queue Length' +# Windows registry subkey of HKEY_LOCAL_MACHINE where the counter names +# of typeperf are registered +COUNTER_REGISTRY_KEY = (r"SOFTWARE\Microsoft\Windows NT\CurrentVersion" + r"\Perflib\CurrentLanguage") class WindowsLoadTracker(): @@ -25,7 +31,8 @@ class WindowsLoadTracker(): def __init__(self): self.load = 0.0 - self.p = None + self.counter_name = '' + self.popen = None self.start() def start(self): @@ -55,31 +62,46 @@ def start(self): overlap.GetOverlappedResult(True) # Spawn off the load monitor - command = ['typeperf', COUNTER_NAME, '-si', str(SAMPLING_INTERVAL)] - self.p = subprocess.Popen(command, stdout=command_stdout, cwd=support.SAVEDCWD) + counter_name = self._get_counter_name() + command = ['typeperf', counter_name, '-si', str(SAMPLING_INTERVAL)] + self.popen = subprocess.Popen(' '.join(command), stdout=command_stdout, cwd=support.SAVEDCWD) # Close our copy of the write end of the pipe os.close(command_stdout) + def _get_counter_name(self): + # accessing the registry to get the counter localization name + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, COUNTER_REGISTRY_KEY) as perfkey: + counters = winreg.QueryValueEx(perfkey, 'Counter')[0] + + # Convert [key1, value1, key2, value2, ...] list + # to {key1: value1, key2: value2, ...} dict + counters = iter(counters) + counters_dict = dict(zip(counters, counters)) + + # System counter has key '2' and Processor Queue Length has key '44' + system = counters_dict['2'] + process_queue_length = counters_dict['44'] + return f'"\\{system}\\{process_queue_length}"' + def close(self): - if self.p is None: + if self.popen is None: return - self.p.kill() - self.p.wait() - self.p = None + self.popen.kill() + self.popen.wait() + self.popen = None def __del__(self): self.close() def read_output(self): - import _winapi - overlapped, _ = _winapi.ReadFile(self.pipe, BUFSIZE, True) bytes_read, res = overlapped.GetOverlappedResult(False) if res != 0: return - return overlapped.getbuffer().decode() + output = overlapped.getbuffer() + return output.decode('oem', 'replace') def getloadavg(self): typeperf_output = self.read_output() @@ -89,14 +111,29 @@ def getloadavg(self): # Process the backlog of load values for line in typeperf_output.splitlines(): + # Ignore the initial header: + # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length" + if '\\\\' in line: + continue + + # Ignore blank lines + if not line.strip(): + continue + # typeperf outputs in a CSV format like this: # "07/19/2018 01:32:26.605","3.000000" - toks = line.split(',') - # Ignore blank lines and the initial header - if line.strip() == '' or (COUNTER_NAME in line) or len(toks) != 2: + # (date, process queue length) + try: + tokens = line.split(',') + if len(tokens) != 2: + raise ValueError + + value = tokens[1].replace('"', '') + load = float(value) + except ValueError: + print_warning("Failed to parse typeperf output: %a" % line) continue - load = float(toks[1].replace('"', '')) # We use an exponentially weighted moving average, imitating the # load calculation on Unix systems. # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation From webhook-mailer at python.org Tue Oct 1 06:45:56 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 01 Oct 2019 10:45:56 -0000 Subject: [Python-checkins] bpo-38321: Fix compiler warning in _randommodule.c (GH-16512) Message-ID: https://github.com/python/cpython/commit/2f90261280e36a179831d72ce794115be31c88bb commit: 2f90261280e36a179831d72ce794115be31c88bb branch: master author: Victor Stinner committer: GitHub date: 2019-10-01T12:45:52+02:00 summary: bpo-38321: Fix compiler warning in _randommodule.c (GH-16512) Fix the GCC warning: "initialization discards ?const? qualifier from pointer target type". files: M Modules/_randommodule.c diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 1ea2bf28abcca..1f4bf74fc7a1e 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -543,7 +543,7 @@ PyDoc_STRVAR(random_doc, "Random() -> create a random number generator with its own internal state."); static PyType_Slot Random_Type_slots[] = { - {Py_tp_doc, random_doc}, + {Py_tp_doc, (void *)random_doc}, {Py_tp_methods, random_methods}, {Py_tp_new, random_new}, {Py_tp_free, PyObject_Free}, From webhook-mailer at python.org Tue Oct 1 06:47:56 2019 From: webhook-mailer at python.org (Miss Islington (bot)) Date: Tue, 01 Oct 2019 10:47:56 -0000 Subject: [Python-checkins] bpo-36670: Multiple regrtest bugfixes (GH-16511) Message-ID: https://github.com/python/cpython/commit/6b4c70abcaa348c84a2c1bb6f5a46596cf358e36 commit: 6b4c70abcaa348c84a2c1bb6f5a46596cf358e36 branch: 3.8 author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com> committer: GitHub date: 2019-10-01T03:47:52-07:00 summary: bpo-36670: Multiple regrtest bugfixes (GH-16511) * Windows: Fix counter name in WindowsLoadTracker. Counter names are localized: use the registry to get the counter name. Original change written by Lorenz Mende. * Regrtest.main() now ensures that the Windows load tracker is also killed if an exception is raised * TestWorkerProcess now ensures that worker processes are no longer running before exiting: kill also worker processes when an exception is raised. * Enhance regrtest messages and warnings: include test name, duration, add a worker identifier, etc. * Rename MultiprocessRunner to TestWorkerProcess * Use print_warning() to display warnings. Co-Authored-By: Lorenz Mende (cherry picked from commit 982bfa4da07b2e5749a0f4e68f99e972bcc3a549) Co-authored-by: Victor Stinner files: M Lib/test/libregrtest/main.py M Lib/test/libregrtest/runtest_mp.py M Lib/test/libregrtest/win_utils.py diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py index 299700686928f..fd701c452ceb5 100644 --- a/Lib/test/libregrtest/main.py +++ b/Lib/test/libregrtest/main.py @@ -508,10 +508,6 @@ def run_tests(self): self.run_tests_sequential() def finalize(self): - if self.win_load_tracker is not None: - self.win_load_tracker.close() - self.win_load_tracker = None - if self.next_single_filename: if self.next_single_test: with open(self.next_single_filename, 'w') as fp: @@ -680,11 +676,16 @@ def _main(self, tests, kwargs): # typeperf.exe for x64, x86 or ARM print(f'Failed to create WindowsLoadTracker: {error}') - self.run_tests() - self.display_result() - - if self.ns.verbose2 and self.bad: - self.rerun_failed_tests() + try: + self.run_tests() + self.display_result() + + if self.ns.verbose2 and self.bad: + self.rerun_failed_tests() + finally: + if self.win_load_tracker is not None: + self.win_load_tracker.close() + self.win_load_tracker = None self.finalize() diff --git a/Lib/test/libregrtest/runtest_mp.py b/Lib/test/libregrtest/runtest_mp.py index 9cb5be6bb8ae8..38b05781de5fc 100644 --- a/Lib/test/libregrtest/runtest_mp.py +++ b/Lib/test/libregrtest/runtest_mp.py @@ -15,7 +15,7 @@ runtest, INTERRUPTED, CHILD_ERROR, PROGRESS_MIN_TIME, format_test_result, TestResult, is_failed, TIMEOUT) from test.libregrtest.setup import setup_tests -from test.libregrtest.utils import format_duration +from test.libregrtest.utils import format_duration, print_warning # Display the running tests if nothing happened last N seconds @@ -103,9 +103,10 @@ class ExitThread(Exception): pass -class MultiprocessThread(threading.Thread): - def __init__(self, pending, output, ns, timeout): +class TestWorkerProcess(threading.Thread): + def __init__(self, worker_id, pending, output, ns, timeout): super().__init__() + self.worker_id = worker_id self.pending = pending self.output = output self.ns = ns @@ -114,12 +115,16 @@ def __init__(self, pending, output, ns, timeout): self.start_time = None self._popen = None self._killed = False + self._stopped = False def __repr__(self): - info = ['MultiprocessThread'] - test = self.current_test_name + info = [f'TestWorkerProcess #{self.worker_id}'] if self.is_alive(): - info.append('alive') + dt = time.monotonic() - self.start_time + info.append("running for %s" % format_duration(dt)) + else: + info.append('stopped') + test = self.current_test_name if test: info.append(f'test={test}') popen = self._popen @@ -128,53 +133,24 @@ def __repr__(self): return '<%s>' % ' '.join(info) def _kill(self): - dt = time.monotonic() - self.start_time + if self._killed: + return + self._killed = True popen = self._popen - pid = popen.pid - print("Kill worker process %s running for %.1f sec" % (pid, dt), - file=sys.stderr, flush=True) + if popen is None: + return + print(f"Kill {self}", file=sys.stderr, flush=True) try: popen.kill() - return True except OSError as exc: - print("WARNING: Failed to kill worker process %s: %r" % (pid, exc), - file=sys.stderr, flush=True) - return False - - def _close_wait(self): - popen = self._popen - - # stdout and stderr must be closed to ensure that communicate() - # does not hang - popen.stdout.close() - popen.stderr.close() - - try: - popen.wait(JOIN_TIMEOUT) - except (subprocess.TimeoutExpired, OSError) as exc: - print("WARNING: Failed to wait for worker process %s " - "completion (timeout=%.1f sec): %r" - % (popen.pid, JOIN_TIMEOUT, exc), - file=sys.stderr, flush=True) - - def kill(self): - """ - Kill the current process (if any). - - This method can be called by the thread running the process, - or by another thread. - """ - self._killed = True - - if self._popen is None: - return - - if not self._kill(): - return + print_warning(f"Failed to kill {self}: {exc!r}") - self._close_wait() + def stop(self): + # Method called from a different thread to stop this thread + self._stopped = True + self._kill() def mp_result_error(self, test_name, error_type, stdout='', stderr='', err_msg=None): @@ -190,59 +166,69 @@ def _timedout(self, test_name): try: stdout, stderr = popen.communicate(timeout=JOIN_TIMEOUT) except (subprocess.TimeoutExpired, OSError) as exc: - print("WARNING: Failed to read worker process %s output " - "(timeout=%.1f sec): %r" - % (popen.pid, JOIN_TIMEOUT, exc), - file=sys.stderr, flush=True) - - self._close_wait() + print_warning(f"Failed to read {self} output " + f"(timeout={format_duration(JOIN_TIMEOUT)}): " + f"{exc!r}") return self.mp_result_error(test_name, TIMEOUT, stdout, stderr) - def _runtest(self, test_name): - try: - self.start_time = time.monotonic() - self.current_test_name = test_name + def _run_process(self, test_name): + self.start_time = time.monotonic() + self.current_test_name = test_name + try: + self._killed = False self._popen = run_test_in_subprocess(test_name, self.ns) popen = self._popen + except: + self.current_test_name = None + raise + + try: + if self._stopped: + # If kill() has been called before self._popen is set, + # self._popen is still running. Call again kill() + # to ensure that the process is killed. + self._kill() + raise ExitThread + try: - try: - if self._killed: - # If kill() has been called before self._popen is set, - # self._popen is still running. Call again kill() - # to ensure that the process is killed. - self.kill() - raise ExitThread - - try: - stdout, stderr = popen.communicate(timeout=self.timeout) - except subprocess.TimeoutExpired: - if self._killed: - # kill() has been called: communicate() fails - # on reading closed stdout/stderr - raise ExitThread - - return self._timedout(test_name) - except OSError: - if self._killed: - # kill() has been called: communicate() fails - # on reading closed stdout/stderr - raise ExitThread - raise - except: - self.kill() - raise - finally: - self._close_wait() + stdout, stderr = popen.communicate(timeout=self.timeout) + except subprocess.TimeoutExpired: + if self._stopped: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + + return self._timedout(test_name) + except OSError: + if self._stopped: + # kill() has been called: communicate() fails + # on reading closed stdout/stderr + raise ExitThread + raise retcode = popen.returncode + stdout = stdout.strip() + stderr = stderr.rstrip() + + return (retcode, stdout, stderr) + except: + self._kill() + raise finally: - self.current_test_name = None + self._wait_completed() self._popen = None + self.current_test_name = None + + def _runtest(self, test_name): + result = self._run_process(test_name) - stdout = stdout.strip() - stderr = stderr.rstrip() + if isinstance(result, MultiprocessResult): + # _timedout() case + return result + + retcode, stdout, stderr = result err_msg = None if retcode != 0: @@ -266,7 +252,7 @@ def _runtest(self, test_name): return MultiprocessResult(result, stdout, stderr, err_msg) def run(self): - while not self._killed: + while not self._stopped: try: try: test_name = next(self.pending) @@ -284,6 +270,33 @@ def run(self): self.output.put((True, traceback.format_exc())) break + def _wait_completed(self): + popen = self._popen + + # stdout and stderr must be closed to ensure that communicate() + # does not hang + popen.stdout.close() + popen.stderr.close() + + try: + popen.wait(JOIN_TIMEOUT) + except (subprocess.TimeoutExpired, OSError) as exc: + print_warning(f"Failed to wait for {self} completion " + f"(timeout={format_duration(JOIN_TIMEOUT)}): " + f"{exc!r}") + + def wait_stopped(self, start_time): + while True: + # Write a message every second + self.join(1.0) + if not self.is_alive(): + break + dt = time.monotonic() - start_time + print(f"Waiting for {self} thread for {format_duration(dt)}", flush=True) + if dt > JOIN_TIMEOUT: + print_warning(f"Failed to join {self} in {format_duration(dt)}") + break + def get_running(workers): running = [] @@ -298,7 +311,7 @@ def get_running(workers): return running -class MultiprocessRunner: +class MultiprocessTestRunner: def __init__(self, regrtest): self.regrtest = regrtest self.ns = regrtest.ns @@ -311,30 +324,20 @@ def __init__(self, regrtest): self.workers = None def start_workers(self): - self.workers = [MultiprocessThread(self.pending, self.output, - self.ns, self.worker_timeout) - for _ in range(self.ns.use_mp)] + self.workers = [TestWorkerProcess(index, self.pending, self.output, + self.ns, self.worker_timeout) + for index in range(1, self.ns.use_mp + 1)] print("Run tests in parallel using %s child processes" % len(self.workers)) for worker in self.workers: worker.start() - def wait_workers(self): + def stop_workers(self): start_time = time.monotonic() for worker in self.workers: - worker.kill() + worker.stop() for worker in self.workers: - while True: - worker.join(1.0) - if not worker.is_alive(): - break - dt = time.monotonic() - start_time - print("Wait for regrtest worker %r for %.1f sec" % (worker, dt), - flush=True) - if dt > JOIN_TIMEOUT: - print("Warning -- failed to join a regrtest worker %s" - % worker, flush=True) - break + worker.wait_stopped(start_time) def _get_result(self): if not any(worker.is_alive() for worker in self.workers): @@ -418,10 +421,11 @@ def run_tests(self): if self.ns.timeout is not None: faulthandler.cancel_dump_traceback_later() - # a test failed (and --failfast is set) or all tests completed - self.pending.stop() - self.wait_workers() + # Always ensure that all worker processes are no longer + # worker when we exit this function + self.pending.stop() + self.stop_workers() def run_tests_multiprocess(regrtest): - MultiprocessRunner(regrtest).run_tests() + MultiprocessTestRunner(regrtest).run_tests() diff --git a/Lib/test/libregrtest/win_utils.py b/Lib/test/libregrtest/win_utils.py index ec2d6c663e83f..f0c17b906f519 100644 --- a/Lib/test/libregrtest/win_utils.py +++ b/Lib/test/libregrtest/win_utils.py @@ -3,16 +3,22 @@ import os import subprocess import uuid +import winreg from test import support +from test.libregrtest.utils import print_warning # Max size of asynchronous reads BUFSIZE = 8192 # Exponential damping factor (see below) LOAD_FACTOR_1 = 0.9200444146293232478931553241 + # Seconds per measurement SAMPLING_INTERVAL = 5 -COUNTER_NAME = r'\System\Processor Queue Length' +# Windows registry subkey of HKEY_LOCAL_MACHINE where the counter names +# of typeperf are registered +COUNTER_REGISTRY_KEY = (r"SOFTWARE\Microsoft\Windows NT\CurrentVersion" + r"\Perflib\CurrentLanguage") class WindowsLoadTracker(): @@ -25,7 +31,8 @@ class WindowsLoadTracker(): def __init__(self): self.load = 0.0 - self.p = None + self.counter_name = '' + self.popen = None self.start() def start(self): @@ -55,31 +62,46 @@ def start(self): overlap.GetOverlappedResult(True) # Spawn off the load monitor - command = ['typeperf', COUNTER_NAME, '-si', str(SAMPLING_INTERVAL)] - self.p = subprocess.Popen(command, stdout=command_stdout, cwd=support.SAVEDCWD) + counter_name = self._get_counter_name() + command = ['typeperf', counter_name, '-si', str(SAMPLING_INTERVAL)] + self.popen = subprocess.Popen(' '.join(command), stdout=command_stdout, cwd=support.SAVEDCWD) # Close our copy of the write end of the pipe os.close(command_stdout) + def _get_counter_name(self): + # accessing the registry to get the counter localization name + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, COUNTER_REGISTRY_KEY) as perfkey: + counters = winreg.QueryValueEx(perfkey, 'Counter')[0] + + # Convert [key1, value1, key2, value2, ...] list + # to {key1: value1, key2: value2, ...} dict + counters = iter(counters) + counters_dict = dict(zip(counters, counters)) + + # System counter has key '2' and Processor Queue Length has key '44' + system = counters_dict['2'] + process_queue_length = counters_dict['44'] + return f'"\\{system}\\{process_queue_length}"' + def close(self): - if self.p is None: + if self.popen is None: return - self.p.kill() - self.p.wait() - self.p = None + self.popen.kill() + self.popen.wait() + self.popen = None def __del__(self): self.close() def read_output(self): - import _winapi - overlapped, _ = _winapi.ReadFile(self.pipe, BUFSIZE, True) bytes_read, res = overlapped.GetOverlappedResult(False) if res != 0: return - return overlapped.getbuffer().decode() + output = overlapped.getbuffer() + return output.decode('oem', 'replace') def getloadavg(self): typeperf_output = self.read_output() @@ -89,14 +111,29 @@ def getloadavg(self): # Process the backlog of load values for line in typeperf_output.splitlines(): + # Ignore the initial header: + # "(PDH-CSV 4.0)","\\\\WIN\\System\\Processor Queue Length" + if '\\\\' in line: + continue + + # Ignore blank lines + if not line.strip(): + continue + # typeperf outputs in a CSV format like this: # "07/19/2018 01:32:26.605","3.000000" - toks = line.split(',') - # Ignore blank lines and the initial header - if line.strip() == '' or (COUNTER_NAME in line) or len(toks) != 2: + # (date, process queue length) + try: + tokens = line.split(',') + if len(tokens) != 2: + raise ValueError + + value = tokens[1].replace('"', '') + load = float(value) + except ValueError: + print_warning("Failed to parse typeperf output: %a" % line) continue - load = float(toks[1].replace('"', '')) # We use an exponentially weighted moving average, imitating the # load calculation on Unix systems. # https://en.wikipedia.org/wiki/Load_(computing)#Unix-style_load_calculation From webhook-mailer at python.org Tue Oct 1 06:58:04 2019 From: webhook-mailer at python.org (Victor Stinner) Date: Tue, 01 Oct 2019 10:58:04 -0000 Subject: [Python-checkins] [2.7] bpo-38243: Escape the server title of DocXMLRPCServer (GH-16447) Message-ID: https://github.com/python/cpython/commit/8eb64155ff26823542ccf0225b3d57b6ae36ea89 commit: 8eb64155ff26823542ccf0225b3d57b6ae36ea89 branch: 2.7 author: Dong-hee Na committer: Victor Stinner date: 2019-10-01T12:58:00+02:00 summary: [2.7] bpo-38243: Escape the server title of DocXMLRPCServer (GH-16447) Escape the server title of DocXMLRPCServer.DocXMLRPCServer when rendering the document page as HTML. files: A Misc/NEWS.d/next/Security/2019-09-25-13-21-09.bpo-38243.1pfz24.rst M Lib/DocXMLRPCServer.py M Lib/test/test_docxmlrpc.py diff --git a/Lib/DocXMLRPCServer.py b/Lib/DocXMLRPCServer.py index 4064ec2e48d4d..90b037dd35d6b 100644 --- a/Lib/DocXMLRPCServer.py +++ b/Lib/DocXMLRPCServer.py @@ -20,6 +20,16 @@ CGIXMLRPCRequestHandler, resolve_dotted_attribute) + +def _html_escape_quote(s): + s = s.replace("&", "&") # Must be done first! + s = s.replace("<", "<") + s = s.replace(">", ">") + s = s.replace('"', """) + s = s.replace('\'', "'") + return s + + class ServerHTMLDoc(pydoc.HTMLDoc): """Class used to generate pydoc HTML document for a server""" @@ -210,7 +220,8 @@ def generate_html_documentation(self): methods ) - return documenter.page(self.server_title, documentation) + title = _html_escape_quote(self.server_title) + return documenter.page(title, documentation) class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): """XML-RPC and documentation request handler class. diff --git a/Lib/test/test_docxmlrpc.py b/Lib/test/test_docxmlrpc.py index 4dff4159e2466..c45b892b8b3e7 100644 --- a/Lib/test/test_docxmlrpc.py +++ b/Lib/test/test_docxmlrpc.py @@ -1,5 +1,6 @@ from DocXMLRPCServer import DocXMLRPCServer import httplib +import re import sys from test import test_support threading = test_support.import_module('threading') @@ -176,6 +177,25 @@ def test_autolink_dotted_methods(self): self.assertIn("""Try self.add, too.""", response.read()) + def test_server_title_escape(self): + """Test that the server title and documentation + are escaped for HTML. + """ + self.serv.set_server_title('test_title