From c422167749f92d4170203e996a2c619c818335ea Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 21 Sep 2019 01:02:56 +0200 Subject: [PATCH] bpo-38234: Remove _PyPathConfig.dll_path (GH-16307) The DLL path is not computed from any user configuration and cannot be configured by PyConfig. Instead, add a new _Py_dll_path global variable. Remove _PyConfig_SetPathConfig(): replaced with _PyPathConfig_Init(). Py_Initialize() now longer sets the "global path configuration", but only initialize _Py_dll_path. --- Include/internal/pycore_initconfig.h | 2 - Include/internal/pycore_pathconfig.h | 10 ++- PC/getpathp.c | 59 ++++++++------- Python/pathconfig.c | 105 +++++++++++---------------- Python/pylifecycle.c | 4 +- 5 files changed, 85 insertions(+), 95 deletions(-) diff --git a/Include/internal/pycore_initconfig.h b/Include/internal/pycore_initconfig.h index c0b3d957827..a7c1994eca1 100644 --- a/Include/internal/pycore_initconfig.h +++ b/Include/internal/pycore_initconfig.h @@ -149,8 +149,6 @@ extern PyStatus _PyConfig_Copy( PyConfig *config, const PyConfig *config2); extern PyStatus _PyConfig_InitPathConfig(PyConfig *config); -extern PyStatus _PyConfig_SetPathConfig( - const PyConfig *config); extern void _PyConfig_Write(const PyConfig *config, _PyRuntimeState *runtime); extern PyStatus _PyConfig_SetPyArgv( diff --git a/Include/internal/pycore_pathconfig.h b/Include/internal/pycore_pathconfig.h index 9e0ba0b01a8..a2c488cdc2e 100644 --- a/Include/internal/pycore_pathconfig.h +++ b/Include/internal/pycore_pathconfig.h @@ -13,10 +13,7 @@ typedef struct _PyPathConfig { wchar_t *program_full_path; wchar_t *prefix; wchar_t *exec_prefix; -#ifdef MS_WINDOWS - wchar_t *dll_path; -#endif - /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ + /* Set by Py_SetPath(), or computed by _PyConfig_InitPathConfig() */ wchar_t *module_search_path; /* Python program name */ wchar_t *program_name; @@ -38,6 +35,9 @@ typedef struct _PyPathConfig { /* Note: _PyPathConfig_INIT sets other fields to 0/NULL */ PyAPI_DATA(_PyPathConfig) _Py_path_config; +#ifdef MS_WINDOWS +PyAPI_DATA(wchar_t*) _Py_dll_path; +#endif extern void _PyPathConfig_ClearGlobal(void); extern PyStatus _PyPathConfig_SetGlobal( @@ -59,6 +59,8 @@ extern int _Py_FindEnvConfigValue( extern wchar_t* _Py_GetDLLPath(void); #endif +extern PyStatus _PyPathConfig_Init(void); + #ifdef __cplusplus } #endif diff --git a/PC/getpathp.c b/PC/getpathp.c index 7465d314b04..01455a660be 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -128,6 +128,8 @@ typedef struct { wchar_t argv0_path[MAXPATHLEN+1]; wchar_t zip_path[MAXPATHLEN+1]; + + wchar_t *dll_path; } PyCalculatePath; @@ -666,28 +668,36 @@ error: } -static void +static PyStatus calculate_init(PyCalculatePath *calculate, const PyConfig *config) { calculate->home = config->home; calculate->path_env = _wgetenv(L"PATH"); + + calculate->dll_path = _Py_GetDLLPath(); + if (calculate->dll_path == NULL) { + return _PyStatus_NO_MEMORY(); + } + + return _PyStatus_OK(); } static int -get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig) +get_pth_filename(PyCalculatePath *calculate, wchar_t *filename, + const _PyPathConfig *pathconfig) { - if (pathconfig->dll_path[0]) { - if (!change_ext(spbuffer, pathconfig->dll_path, L"._pth") && - exists(spbuffer)) + if (calculate->dll_path[0]) { + if (!change_ext(filename, calculate->dll_path, L"._pth") && + exists(filename)) { return 1; } } if (pathconfig->program_full_path[0]) { - if (!change_ext(spbuffer, pathconfig->program_full_path, L"._pth") && - exists(spbuffer)) + if (!change_ext(filename, pathconfig->program_full_path, L"._pth") && + exists(filename)) { return 1; } @@ -697,15 +707,16 @@ get_pth_filename(wchar_t *spbuffer, _PyPathConfig *pathconfig) static int -calculate_pth_file(_PyPathConfig *pathconfig, wchar_t *prefix) +calculate_pth_file(PyCalculatePath *calculate, _PyPathConfig *pathconfig, + wchar_t *prefix) { - wchar_t spbuffer[MAXPATHLEN+1]; + wchar_t filename[MAXPATHLEN+1]; - if (!get_pth_filename(spbuffer, pathconfig)) { + if (!get_pth_filename(calculate, filename, pathconfig)) { return 0; } - return read_pth_file(pathconfig, prefix, spbuffer); + return read_pth_file(pathconfig, prefix, filename); } @@ -966,13 +977,6 @@ calculate_path_impl(const PyConfig *config, { PyStatus status; - assert(pathconfig->dll_path == NULL); - - pathconfig->dll_path = _Py_GetDLLPath(); - if (pathconfig->dll_path == NULL) { - return _PyStatus_NO_MEMORY(); - } - status = get_program_full_path(config, calculate, pathconfig); if (_PyStatus_EXCEPTION(status)) { return status; @@ -986,7 +990,7 @@ calculate_path_impl(const PyConfig *config, memset(prefix, 0, sizeof(prefix)); /* Search for a sys.path file */ - if (calculate_pth_file(pathconfig, prefix)) { + if (calculate_pth_file(calculate, pathconfig, prefix)) { goto done; } @@ -994,7 +998,7 @@ calculate_path_impl(const PyConfig *config, /* Calculate zip archive path from DLL or exe path */ change_ext(calculate->zip_path, - pathconfig->dll_path[0] ? pathconfig->dll_path : pathconfig->program_full_path, + calculate->dll_path[0] ? calculate->dll_path : pathconfig->program_full_path, L".zip"); calculate_home_prefix(calculate, prefix); @@ -1023,23 +1027,23 @@ calculate_free(PyCalculatePath *calculate) { PyMem_RawFree(calculate->machine_path); PyMem_RawFree(calculate->user_path); + PyMem_RawFree(calculate->dll_path); } PyStatus _PyPathConfig_Calculate(_PyPathConfig *pathconfig, const PyConfig *config) { + PyStatus status; PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - calculate_init(&calculate, config); - - PyStatus status = calculate_path_impl(config, &calculate, pathconfig); + status = calculate_init(&calculate, config); if (_PyStatus_EXCEPTION(status)) { goto done; } - status = _PyStatus_OK(); + status = calculate_path_impl(config, &calculate, pathconfig); done: calculate_free(&calculate); @@ -1067,7 +1071,12 @@ _Py_CheckPython3(void) /* If there is a python3.dll next to the python3y.dll, assume this is a build tree; use that DLL */ - wcscpy(py3path, _Py_path_config.dll_path); + if (_Py_dll_path != NULL) { + wcscpy(py3path, _Py_dll_path); + } + else { + wcscpy(py3path, L""); + } s = wcsrchr(py3path, L'\\'); if (!s) { s = py3path; diff --git a/Python/pathconfig.c b/Python/pathconfig.c index ee220611357..ccab8327425 100644 --- a/Python/pathconfig.c +++ b/Python/pathconfig.c @@ -15,6 +15,9 @@ extern "C" { _PyPathConfig _Py_path_config = _PyPathConfig_INIT; +#ifdef MS_WINDOWS +wchar_t *_Py_dll_path = NULL; +#endif static int @@ -51,9 +54,6 @@ pathconfig_clear(_PyPathConfig *config) CLEAR(config->prefix); CLEAR(config->program_full_path); CLEAR(config->exec_prefix); -#ifdef MS_WINDOWS - CLEAR(config->dll_path); -#endif CLEAR(config->module_search_path); CLEAR(config->home); CLEAR(config->program_name); @@ -114,47 +114,6 @@ done: } -PyStatus -_PyPathConfig_SetGlobal(const _PyPathConfig *config) -{ - PyStatus status; - _PyPathConfig new_config = _PyPathConfig_INIT; - - PyMemAllocatorEx old_alloc; - _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - -#define COPY_ATTR(ATTR) \ - do { \ - if (copy_wstr(&new_config.ATTR, config->ATTR) < 0) { \ - pathconfig_clear(&new_config); \ - status = _PyStatus_NO_MEMORY(); \ - goto done; \ - } \ - } while (0) - - COPY_ATTR(program_full_path); - COPY_ATTR(prefix); - COPY_ATTR(exec_prefix); -#ifdef MS_WINDOWS - COPY_ATTR(dll_path); -#endif - COPY_ATTR(module_search_path); - COPY_ATTR(program_name); - COPY_ATTR(home); - COPY_ATTR(base_executable); - - pathconfig_clear(&_Py_path_config); - /* Steal new_config strings; don't clear new_config */ - _Py_path_config = new_config; - - status = _PyStatus_OK(); - -done: - PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - return status; -} - - void _PyPathConfig_ClearGlobal(void) { @@ -162,6 +121,10 @@ _PyPathConfig_ClearGlobal(void) _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); pathconfig_clear(&_Py_path_config); +#ifdef MS_WINDOWS + PyMem_RawFree(_Py_dll_path); + _Py_dll_path = NULL; +#endif PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } @@ -200,12 +163,36 @@ _PyWideStringList_Join(const PyWideStringList *list, wchar_t sep) /* Set the global path configuration from config. */ PyStatus -_PyConfig_SetPathConfig(const PyConfig *config) +_PyPathConfig_Init(void) { +#ifdef MS_WINDOWS + if (_Py_dll_path == NULL) { + /* Already set: nothing to do */ + return _PyStatus_OK(); + } + PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + _Py_dll_path = _Py_GetDLLPath(); + + PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + + if (_Py_dll_path == NULL) { + return _PyStatus_NO_MEMORY(); + } +#endif + return _PyStatus_OK(); +} + + +static PyStatus +pathconfig_global_init_from_config(const PyConfig *config) +{ PyStatus status; + PyMemAllocatorEx old_alloc; + _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); + _PyPathConfig pathconfig = _PyPathConfig_INIT; pathconfig.module_search_path = _PyWideStringList_Join(&config->module_search_paths, DELIM); @@ -222,12 +209,6 @@ _PyConfig_SetPathConfig(const PyConfig *config) if (copy_wstr(&pathconfig.exec_prefix, config->exec_prefix) < 0) { goto no_memory; } -#ifdef MS_WINDOWS - pathconfig.dll_path = _Py_GetDLLPath(); - if (pathconfig.dll_path == NULL) { - goto no_memory; - } -#endif if (copy_wstr(&pathconfig.program_name, config->program_name) < 0) { goto no_memory; } @@ -238,19 +219,18 @@ _PyConfig_SetPathConfig(const PyConfig *config) goto no_memory; } - status = _PyPathConfig_SetGlobal(&pathconfig); - if (_PyStatus_EXCEPTION(status)) { - goto done; - } + pathconfig_clear(&_Py_path_config); + /* Steal new_config strings; don't clear new_config */ + _Py_path_config = pathconfig; status = _PyStatus_OK(); goto done; no_memory: + pathconfig_clear(&pathconfig); status = _PyStatus_NO_MEMORY(); done: - pathconfig_clear(&pathconfig); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); return status; } @@ -402,12 +382,17 @@ _PyConfig_InitPathConfig(PyConfig *config) static void pathconfig_global_init(void) { + /* Initialize _Py_dll_path if needed */ + PyStatus status = _PyPathConfig_Init(); + if (_PyStatus_EXCEPTION(status)) { + Py_ExitStatusException(status); + } + if (_Py_path_config.module_search_path != NULL) { /* Already initialized */ return; } - PyStatus status; PyConfig config; _PyConfig_InitCompatConfig(&config); @@ -416,7 +401,7 @@ pathconfig_global_init(void) goto error; } - status = _PyConfig_SetPathConfig(&config); + status = pathconfig_global_init_from_config(&config); if (_PyStatus_EXCEPTION(status)) { goto error; } @@ -450,10 +435,6 @@ Py_SetPath(const wchar_t *path) alloc_error |= (new_config.prefix == NULL); new_config.exec_prefix = _PyMem_RawWcsdup(L""); alloc_error |= (new_config.exec_prefix == NULL); -#ifdef MS_WINDOWS - new_config.dll_path = _Py_GetDLLPath(); - alloc_error |= (new_config.dll_path == NULL); -#endif new_config.module_search_path = _PyMem_RawWcsdup(path); alloc_error |= (new_config.module_search_path == NULL); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index f9ff8f41807..e5b6283d8db 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -475,7 +475,7 @@ pyinit_core_reconfigure(_PyRuntimeState *runtime, config = &interp->config; if (config->_install_importlib) { - status = _PyConfig_SetPathConfig(config); + status = _PyPathConfig_Init(); if (_PyStatus_EXCEPTION(status)) { return status; } @@ -646,7 +646,7 @@ pycore_init_import_warnings(PyThreadState *tstate, PyObject *sysmod) } if (config->_install_importlib) { - status = _PyConfig_SetPathConfig(config); + status = _PyPathConfig_Init(); if (_PyStatus_EXCEPTION(status)) { return status; }