diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h index ff915323386..d32c98b6985 100644 --- a/Include/pylifecycle.h +++ b/Include/pylifecycle.h @@ -103,8 +103,9 @@ PyAPI_FUNC(wchar_t *) Py_GetPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void); PyAPI_FUNC(wchar_t *) Py_GetPath(void); #ifdef Py_BUILD_CORE -PyAPI_FUNC(wchar_t *) _Py_GetPathWithConfig( - const _PyMainInterpreterConfig *config); +PyAPI_FUNC(_PyInitError) _PyPathConfig_Init( + const _PyMainInterpreterConfig *main_config); +PyAPI_FUNC(void) _PyPathConfig_Fini(void); #endif PyAPI_FUNC(void) Py_SetPath(const wchar_t *); #ifdef MS_WINDOWS diff --git a/Modules/getpath.c b/Modules/getpath.c index 9078aa81b32..02d626cea73 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -109,10 +109,16 @@ extern "C" { #define LANDMARK L"os.py" #endif +#define DECODE_LOCALE_ERR(NAME, LEN) \ + ((LEN) == (size_t)-2) \ + ? _Py_INIT_USER_ERR("cannot decode " #NAME) \ + : _Py_INIT_NO_MEMORY() + + typedef struct { - wchar_t prefix[MAXPATHLEN+1]; - wchar_t exec_prefix[MAXPATHLEN+1]; - wchar_t program_name[MAXPATHLEN+1]; + wchar_t *prefix; + wchar_t *exec_prefix; + wchar_t *program_name; wchar_t *module_search_path; } PyPathConfig; @@ -361,63 +367,63 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) bytes long. */ static int -search_for_prefix(PyCalculatePath *calculate, PyPathConfig *config) +search_for_prefix(PyCalculatePath *calculate, wchar_t *prefix) { size_t n; wchar_t *vpath; /* If PYTHONHOME is set, we believe it unconditionally */ if (calculate->home) { - wcsncpy(config->prefix, calculate->home, MAXPATHLEN); - config->prefix[MAXPATHLEN] = L'\0'; - wchar_t *delim = wcschr(config->prefix, DELIM); + wcsncpy(prefix, calculate->home, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; + wchar_t *delim = wcschr(prefix, DELIM); if (delim) { *delim = L'\0'; } - joinpath(config->prefix, calculate->lib_python); - joinpath(config->prefix, LANDMARK); + joinpath(prefix, calculate->lib_python); + joinpath(prefix, LANDMARK); return 1; } /* Check to see if argv[0] is in the build directory */ - wcsncpy(config->prefix, calculate->argv0_path, MAXPATHLEN); - config->prefix[MAXPATHLEN] = L'\0'; - joinpath(config->prefix, L"Modules/Setup"); - if (isfile(config->prefix)) { + wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; + joinpath(prefix, L"Modules/Setup"); + if (isfile(prefix)) { /* Check VPATH to see if argv0_path is in the build directory. */ vpath = Py_DecodeLocale(VPATH, NULL); if (vpath != NULL) { - wcsncpy(config->prefix, calculate->argv0_path, MAXPATHLEN); - config->prefix[MAXPATHLEN] = L'\0'; - joinpath(config->prefix, vpath); + wcsncpy(prefix, calculate->argv0_path, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; + joinpath(prefix, vpath); PyMem_RawFree(vpath); - joinpath(config->prefix, L"Lib"); - joinpath(config->prefix, LANDMARK); - if (ismodule(config->prefix)) { + joinpath(prefix, L"Lib"); + joinpath(prefix, LANDMARK); + if (ismodule(prefix)) { return -1; } } } /* Search from argv0_path, until root is found */ - copy_absolute(config->prefix, calculate->argv0_path, MAXPATHLEN+1); + copy_absolute(prefix, calculate->argv0_path, MAXPATHLEN+1); do { - n = wcslen(config->prefix); - joinpath(config->prefix, calculate->lib_python); - joinpath(config->prefix, LANDMARK); - if (ismodule(config->prefix)) { + n = wcslen(prefix); + joinpath(prefix, calculate->lib_python); + joinpath(prefix, LANDMARK); + if (ismodule(prefix)) { return 1; } - config->prefix[n] = L'\0'; - reduce(config->prefix); - } while (config->prefix[0]); + prefix[n] = L'\0'; + reduce(prefix); + } while (prefix[0]); /* Look at configure's PREFIX */ - wcsncpy(config->prefix, calculate->prefix, MAXPATHLEN); - config->prefix[MAXPATHLEN] = L'\0'; - joinpath(config->prefix, calculate->lib_python); - joinpath(config->prefix, LANDMARK); - if (ismodule(config->prefix)) { + wcsncpy(prefix, calculate->prefix, MAXPATHLEN); + prefix[MAXPATHLEN] = L'\0'; + joinpath(prefix, calculate->lib_python); + joinpath(prefix, LANDMARK); + if (ismodule(prefix)) { return 1; } @@ -427,25 +433,25 @@ search_for_prefix(PyCalculatePath *calculate, PyPathConfig *config) static void -calculate_prefix(PyCalculatePath *calculate, PyPathConfig *config) +calculate_prefix(PyCalculatePath *calculate, wchar_t *prefix) { - calculate->prefix_found = search_for_prefix(calculate, config); + calculate->prefix_found = search_for_prefix(calculate, prefix); if (!calculate->prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, "Could not find platform independent libraries \n"); } - wcsncpy(config->prefix, calculate->prefix, MAXPATHLEN); - joinpath(config->prefix, calculate->lib_python); + wcsncpy(prefix, calculate->prefix, MAXPATHLEN); + joinpath(prefix, calculate->lib_python); } else { - reduce(config->prefix); + reduce(prefix); } } static void -calculate_reduce_prefix(PyCalculatePath *calculate, PyPathConfig *config) +calculate_reduce_prefix(PyCalculatePath *calculate, wchar_t *prefix) { /* Reduce prefix and exec_prefix to their essence, * e.g. /usr/local/lib/python1.5 is reduced to /usr/local. @@ -453,16 +459,16 @@ calculate_reduce_prefix(PyCalculatePath *calculate, PyPathConfig *config) * return the compiled-in defaults instead. */ if (calculate->prefix_found > 0) { - reduce(config->prefix); - reduce(config->prefix); + reduce(prefix); + reduce(prefix); /* The prefix is the root directory, but reduce() chopped * off the "/". */ - if (!config->prefix[0]) { - wcscpy(config->prefix, separator); + if (!prefix[0]) { + wcscpy(prefix, separator); } } else { - wcsncpy(config->prefix, calculate->prefix, MAXPATHLEN); + wcsncpy(prefix, calculate->prefix, MAXPATHLEN); } } @@ -471,7 +477,7 @@ calculate_reduce_prefix(PyCalculatePath *calculate, PyPathConfig *config) MAXPATHLEN bytes long. */ static int -search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) +search_for_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) { size_t n; @@ -479,25 +485,25 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) if (calculate->home) { wchar_t *delim = wcschr(calculate->home, DELIM); if (delim) { - wcsncpy(config->exec_prefix, delim+1, MAXPATHLEN); + wcsncpy(exec_prefix, delim+1, MAXPATHLEN); } else { - wcsncpy(config->exec_prefix, calculate->home, MAXPATHLEN); + wcsncpy(exec_prefix, calculate->home, MAXPATHLEN); } - config->exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(config->exec_prefix, calculate->lib_python); - joinpath(config->exec_prefix, L"lib-dynload"); + exec_prefix[MAXPATHLEN] = L'\0'; + joinpath(exec_prefix, calculate->lib_python); + joinpath(exec_prefix, L"lib-dynload"); return 1; } /* Check to see if argv[0] is in the build directory. "pybuilddir.txt" is written by setup.py and contains the relative path to the location of shared library modules. */ - wcsncpy(config->exec_prefix, calculate->argv0_path, MAXPATHLEN); - config->exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(config->exec_prefix, L"pybuilddir.txt"); - if (isfile(config->exec_prefix)) { - FILE *f = _Py_wfopen(config->exec_prefix, L"rb"); + wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; + joinpath(exec_prefix, L"pybuilddir.txt"); + if (isfile(exec_prefix)) { + FILE *f = _Py_wfopen(exec_prefix, L"rb"); if (f == NULL) { errno = 0; } @@ -516,9 +522,9 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) Py_DECREF(decoded); if (k >= 0) { rel_builddir_path[k] = L'\0'; - wcsncpy(config->exec_prefix, calculate->argv0_path, MAXPATHLEN); - config->exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(config->exec_prefix, rel_builddir_path); + wcsncpy(exec_prefix, calculate->argv0_path, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; + joinpath(exec_prefix, rel_builddir_path); return -1; } } @@ -526,24 +532,24 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) } /* Search from argv0_path, until root is found */ - copy_absolute(config->exec_prefix, calculate->argv0_path, MAXPATHLEN+1); + copy_absolute(exec_prefix, calculate->argv0_path, MAXPATHLEN+1); do { - n = wcslen(config->exec_prefix); - joinpath(config->exec_prefix, calculate->lib_python); - joinpath(config->exec_prefix, L"lib-dynload"); - if (isdir(config->exec_prefix)) { + n = wcslen(exec_prefix); + joinpath(exec_prefix, calculate->lib_python); + joinpath(exec_prefix, L"lib-dynload"); + if (isdir(exec_prefix)) { return 1; } - config->exec_prefix[n] = L'\0'; - reduce(config->exec_prefix); - } while (config->exec_prefix[0]); + exec_prefix[n] = L'\0'; + reduce(exec_prefix); + } while (exec_prefix[0]); /* Look at configure's EXEC_PREFIX */ - wcsncpy(config->exec_prefix, calculate->exec_prefix, MAXPATHLEN); - config->exec_prefix[MAXPATHLEN] = L'\0'; - joinpath(config->exec_prefix, calculate->lib_python); - joinpath(config->exec_prefix, L"lib-dynload"); - if (isdir(config->exec_prefix)) { + wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); + exec_prefix[MAXPATHLEN] = L'\0'; + joinpath(exec_prefix, calculate->lib_python); + joinpath(exec_prefix, L"lib-dynload"); + if (isdir(exec_prefix)) { return 1; } @@ -553,41 +559,44 @@ search_for_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) static void -calculate_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) +calculate_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) { - calculate->exec_prefix_found = search_for_exec_prefix(calculate, config); + calculate->exec_prefix_found = search_for_exec_prefix(calculate, exec_prefix); if (!calculate->exec_prefix_found) { if (!Py_FrozenFlag) { fprintf(stderr, "Could not find platform dependent libraries \n"); } - wcsncpy(config->exec_prefix, calculate->exec_prefix, MAXPATHLEN); - joinpath(config->exec_prefix, L"lib/lib-dynload"); + wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); + joinpath(exec_prefix, L"lib/lib-dynload"); } /* If we found EXEC_PREFIX do *not* reduce it! (Yet.) */ } static void -calculate_reduce_exec_prefix(PyCalculatePath *calculate, PyPathConfig *config) +calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) { if (calculate->exec_prefix_found > 0) { - reduce(config->exec_prefix); - reduce(config->exec_prefix); - reduce(config->exec_prefix); - if (!config->exec_prefix[0]) { - wcscpy(config->exec_prefix, separator); + reduce(exec_prefix); + reduce(exec_prefix); + reduce(exec_prefix); + if (!exec_prefix[0]) { + wcscpy(exec_prefix, separator); } } else { - wcsncpy(config->exec_prefix, calculate->exec_prefix, MAXPATHLEN); + wcsncpy(exec_prefix, calculate->exec_prefix, MAXPATHLEN); } } -static void -calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config) +static _PyInitError +calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) { + wchar_t program_name[MAXPATHLEN+1]; + memset(program_name, 0, sizeof(program_name)); + #ifdef __APPLE__ #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 uint32_t nsexeclength = MAXPATHLEN; @@ -603,7 +612,7 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config) * $PATH isn't exported, you lose. */ if (wcschr(calculate->program_name, SEP)) { - wcsncpy(config->program_name, calculate->program_name, MAXPATHLEN); + wcsncpy(program_name, calculate->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -619,10 +628,10 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config) else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t r = mbstowcs(config->program_name, execpath, MAXPATHLEN+1); + size_t r = mbstowcs(program_name, execpath, MAXPATHLEN+1); if (r == (size_t)-1 || r > MAXPATHLEN) { /* Could not convert execpath, or it's too long. */ - config->program_name[0] = '\0'; + program_name[0] = '\0'; } } #endif /* __APPLE__ */ @@ -636,38 +645,44 @@ calculate_progpath(PyCalculatePath *calculate, PyPathConfig *config) if (len > MAXPATHLEN) { len = MAXPATHLEN; } - wcsncpy(config->program_name, path, len); - *(config->program_name + len) = '\0'; + wcsncpy(program_name, path, len); + program_name[len] = '\0'; } else { - wcsncpy(config->program_name, path, MAXPATHLEN); + wcsncpy(program_name, path, MAXPATHLEN); } - joinpath(config->program_name, calculate->program_name); - if (isxfile(config->program_name)) { + joinpath(program_name, calculate->program_name); + if (isxfile(program_name)) { break; } if (!delim) { - config->program_name[0] = L'\0'; + program_name[0] = L'\0'; break; } path = delim + 1; } } else { - config->program_name[0] = '\0'; + program_name[0] = '\0'; } - if (config->program_name[0] != SEP && config->program_name[0] != '\0') { - absolutize(config->program_name); + if (program_name[0] != SEP && program_name[0] != '\0') { + absolutize(program_name); } + + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); } -static void -calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config) +static _PyInitError +calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) { - wcsncpy(calculate->argv0_path, config->program_name, MAXPATHLEN); + wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN); calculate->argv0_path[MAXPATHLEN] = '\0'; #ifdef WITH_NEXT_FRAMEWORK @@ -690,9 +705,10 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config) ** be running the interpreter in the build directory, so we use the ** build-directory-specific logic to find Lib and such. */ - wchar_t* wbuf = Py_DecodeLocale(modPath, NULL); + size_t len; + wchar_t* wbuf = Py_DecodeLocale(modPath, &len); if (wbuf == NULL) { - Py_FatalError("Cannot decode framework location"); + return DECODE_LOCALE_ERR("framework location", len); } wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN); @@ -702,7 +718,7 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config) if (!ismodule(calculate->argv0_path)) { /* We are in the build directory so use the name of the executable - we know that the absolute path is passed */ - wcsncpy(calculate->argv0_path, config->program_name, MAXPATHLEN); + wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN); } else { /* Use the location of the library as the program_name */ @@ -714,7 +730,7 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config) #if HAVE_READLINK wchar_t tmpbuffer[MAXPATHLEN+1]; - int linklen = _Py_wreadlink(config->program_name, tmpbuffer, MAXPATHLEN); + int linklen = _Py_wreadlink(program_name, tmpbuffer, MAXPATHLEN); while (linklen != -1) { if (tmpbuffer[0] == SEP) { /* tmpbuffer should never be longer than MAXPATHLEN, @@ -733,6 +749,7 @@ calculate_argv0_path(PyCalculatePath *calculate, PyPathConfig *config) reduce(calculate->argv0_path); /* At this point, argv0_path is guaranteed to be less than MAXPATHLEN bytes long. */ + return _Py_INIT_OK(); } @@ -777,9 +794,9 @@ calculate_read_pyenv(PyCalculatePath *calculate) static void -calculate_zip_path(PyCalculatePath *calculate, PyPathConfig *config) +calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) { - wcsncpy(calculate->zip_path, config->prefix, MAXPATHLEN); + wcsncpy(calculate->zip_path, prefix, MAXPATHLEN); calculate->zip_path[MAXPATHLEN] = L'\0'; if (calculate->prefix_found > 0) { @@ -799,8 +816,10 @@ calculate_zip_path(PyCalculatePath *calculate, PyPathConfig *config) } -static wchar_t * -calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config) +static _PyInitError +calculate_module_search_path(PyCalculatePath *calculate, + const wchar_t *prefix, const wchar_t *exec_prefix, + PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; @@ -809,7 +828,7 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config) } wchar_t *defpath = calculate->pythonpath; - size_t prefixsz = wcslen(config->prefix) + 1; + size_t prefixsz = wcslen(prefix) + 1; while (1) { wchar_t *delim = wcschr(defpath, DELIM); @@ -829,13 +848,12 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config) } bufsz += wcslen(calculate->zip_path) + 1; - bufsz += wcslen(config->exec_prefix) + 1; + bufsz += wcslen(exec_prefix) + 1; /* Allocate the buffer */ wchar_t *buf = PyMem_RawMalloc(bufsz * sizeof(wchar_t)); if (buf == NULL) { - Py_FatalError( - "Not enough memory for dynamic PYTHONPATH"); + return _Py_INIT_NO_MEMORY(); } buf[0] = '\0'; @@ -857,8 +875,8 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config) wchar_t *delim = wcschr(defpath, DELIM); if (defpath[0] != SEP) { - wcscat(buf, config->prefix); - if (prefixsz >= 2 && config->prefix[prefixsz - 2] != SEP && + wcscat(buf, prefix); + if (prefixsz >= 2 && prefix[prefixsz - 2] != SEP && defpath[0] != (delim ? DELIM : L'\0')) { /* not empty */ @@ -870,7 +888,7 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config) size_t len = delim - defpath + 1; size_t end = wcslen(buf) + len; wcsncat(buf, defpath, len); - *(buf + end) = '\0'; + buf[end] = '\0'; } else { wcscat(buf, defpath); @@ -881,18 +899,13 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config) wcscat(buf, delimiter); /* Finally, on goes the directory for dynamic-load modules */ - wcscat(buf, config->exec_prefix); + wcscat(buf, exec_prefix); - return buf; + config->module_search_path = buf; + return _Py_INIT_OK(); } -#define DECODE_LOCALE_ERR(NAME, LEN) \ - ((LEN) == (size_t)-2) \ - ? _Py_INIT_USER_ERR("failed to decode " #NAME) \ - : _Py_INIT_NO_MEMORY() - - static _PyInitError calculate_init(PyCalculatePath *calculate, const _PyMainInterpreterConfig *main_config) @@ -941,15 +954,30 @@ calculate_free(PyCalculatePath *calculate) } -static void +static _PyInitError calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config) { - calculate_progpath(calculate, config); - calculate_argv0_path(calculate, config); + _PyInitError err = calculate_program_name(calculate, config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = calculate_argv0_path(calculate, config->program_name); + if (_Py_INIT_FAILED(err)) { + return err; + } + calculate_read_pyenv(calculate); - calculate_prefix(calculate, config); - calculate_zip_path(calculate, config); - calculate_exec_prefix(calculate, config); + + wchar_t prefix[MAXPATHLEN+1]; + memset(prefix, 0, sizeof(prefix)); + calculate_prefix(calculate, prefix); + + calculate_zip_path(calculate, prefix); + + wchar_t exec_prefix[MAXPATHLEN+1]; + memset(exec_prefix, 0, sizeof(exec_prefix)); + calculate_exec_prefix(calculate, exec_prefix); if ((!calculate->prefix_found || !calculate->exec_prefix_found) && !Py_FrozenFlag) @@ -958,53 +986,105 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config) "Consider setting $PYTHONHOME to [:]\n"); } - config->module_search_path = calculate_module_search_path(calculate, config); - calculate_reduce_prefix(calculate, config); - calculate_reduce_exec_prefix(calculate, config); + err = calculate_module_search_path(calculate, prefix, exec_prefix, + config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + calculate_reduce_prefix(calculate, prefix); + + config->prefix = _PyMem_RawWcsdup(prefix); + if (config->prefix == NULL) { + return _Py_INIT_NO_MEMORY(); + } + + calculate_reduce_exec_prefix(calculate, exec_prefix); + + config->exec_prefix = _PyMem_RawWcsdup(exec_prefix); + if (config->exec_prefix == NULL) { + return _Py_INIT_NO_MEMORY(); + } + + return _Py_INIT_OK(); } static void -calculate_path(const _PyMainInterpreterConfig *main_config) +pathconfig_clear(PyPathConfig *config) { - _PyInitError err; +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->prefix); + CLEAR(config->exec_prefix); + CLEAR(config->program_name); + CLEAR(config->module_search_path); +#undef CLEAR +} + + +/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() + and Py_GetProgramFullPath() */ +_PyInitError +_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +{ + if (path_config.module_search_path) { + /* Already initialized */ + return _Py_INIT_OK(); + } + PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - _PyMainInterpreterConfig tmp_config; - int use_tmp = (main_config == NULL); - if (use_tmp) { - tmp_config = _PyMainInterpreterConfig_INIT; - err = _PyMainInterpreterConfig_ReadEnv(&tmp_config); - if (_Py_INIT_FAILED(err)) { - goto fatal_error; - } - main_config = &tmp_config; - } - - err = calculate_init(&calculate, main_config); + _PyInitError err = calculate_init(&calculate, main_config); if (_Py_INIT_FAILED(err)) { - goto fatal_error; + goto done; } PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); - calculate_path_impl(&calculate, &new_path_config); + err = calculate_path_impl(&calculate, &new_path_config); + if (_Py_INIT_FAILED(err)) { + pathconfig_clear(&new_path_config); + goto done; + } + path_config = new_path_config; + err = _Py_INIT_OK(); - if (use_tmp) { - _PyMainInterpreterConfig_Clear(&tmp_config); - } +done: calculate_free(&calculate); - return; + return err; +} -fatal_error: - if (use_tmp) { - _PyMainInterpreterConfig_Clear(&tmp_config); + +static void +calculate_path(void) +{ + _PyInitError err; + _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + + err = _PyMainInterpreterConfig_ReadEnv(&config); + if (!_Py_INIT_FAILED(err)) { + err = _PyPathConfig_Init(&config); } - calculate_free(&calculate); - _Py_FatalInitError(err); + _PyMainInterpreterConfig_Clear(&config); + + if (_Py_INIT_FAILED(err)) { + _Py_FatalInitError(err); + } +} + + +void +_PyPathConfig_Fini(void) +{ + pathconfig_clear(&path_config); } @@ -1012,33 +1092,19 @@ fatal_error: void Py_SetPath(const wchar_t *path) { - if (path_config.module_search_path != NULL) { - PyMem_RawFree(path_config.module_search_path); - path_config.module_search_path = NULL; - } - if (path == NULL) { + pathconfig_clear(&path_config); return; } - wchar_t *program_name = Py_GetProgramName(); - wcsncpy(path_config.program_name, program_name, MAXPATHLEN); - path_config.exec_prefix[0] = path_config.prefix[0] = L'\0'; - size_t size = (wcslen(path) + 1) * sizeof(wchar_t); - path_config.module_search_path = PyMem_RawMalloc(size); - if (path_config.module_search_path != NULL) { - wcscpy(path_config.module_search_path, path); - } -} + PyPathConfig new_config; + new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + new_config.exec_prefix = _PyMem_RawWcsdup(L""); + new_config.prefix = _PyMem_RawWcsdup(L""); + new_config.module_search_path = _PyMem_RawWcsdup(path); - -wchar_t * -_Py_GetPathWithConfig(const _PyMainInterpreterConfig *main_config) -{ - if (!path_config.module_search_path) { - calculate_path(main_config); - } - return path_config.module_search_path; + pathconfig_clear(&path_config); + path_config = new_config; } @@ -1046,7 +1112,7 @@ wchar_t * Py_GetPath(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.module_search_path; } @@ -1056,7 +1122,7 @@ wchar_t * Py_GetPrefix(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.prefix; } @@ -1066,7 +1132,7 @@ wchar_t * Py_GetExecPrefix(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.exec_prefix; } @@ -1076,7 +1142,7 @@ wchar_t * Py_GetProgramFullPath(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.program_name; } diff --git a/Modules/main.c b/Modules/main.c index dca165dad2c..1b1d8041ef1 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -38,14 +38,14 @@ extern "C" { #define DECODE_LOCALE_ERR(NAME, LEN) \ (((LEN) == -2) \ - ? _Py_INIT_USER_ERR("failed to decode " #NAME) \ + ? _Py_INIT_USER_ERR("cannot decode " #NAME) \ : _Py_INIT_NO_MEMORY()) #define SET_DECODE_ERROR(NAME, LEN) \ do { \ if ((LEN) == (size_t)-2) { \ - pymain->err = _Py_INIT_USER_ERR("failed to decode " #NAME); \ + pymain->err = _Py_INIT_USER_ERR("cannot decode " #NAME); \ } \ else { \ pymain->err = _Py_INIT_NO_MEMORY(); \ diff --git a/PC/getpathp.c b/PC/getpathp.c index 38e433b6dcd..fe0226ba5d2 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -117,9 +117,9 @@ #endif typedef struct { - wchar_t prefix[MAXPATHLEN+1]; - wchar_t program_name[MAXPATHLEN+1]; - wchar_t dllpath[MAXPATHLEN+1]; + wchar_t *prefix; + wchar_t *program_name; + wchar_t *dll_path; wchar_t *module_search_path; } PyPathConfig; @@ -483,24 +483,39 @@ done: #endif /* Py_ENABLE_SHARED */ -static void -get_progpath(PyCalculatePath *calculate, PyPathConfig *config) +static _PyInitError +get_dll_path(PyCalculatePath *calculate, PyPathConfig *config) { - wchar_t *path = calculate->path_env; + wchar_t dll_path[MAXPATHLEN+1]; + memset(dll_path, 0, sizeof(dll_path)); #ifdef Py_ENABLE_SHARED extern HANDLE PyWin_DLLhModule; - /* static init of program_name ensures final char remains \0 */ if (PyWin_DLLhModule) { - if (!GetModuleFileNameW(PyWin_DLLhModule, config->dllpath, MAXPATHLEN)) { - config->dllpath[0] = 0; + if (!GetModuleFileNameW(PyWin_DLLhModule, dll_path, MAXPATHLEN)) { + dll_path[0] = 0; } } #else - config->dllpath[0] = 0; + dll_path[0] = 0; #endif - if (GetModuleFileNameW(NULL, config->program_name, MAXPATHLEN)) { - return; + + config->dll_path = _PyMem_RawWcsdup(dll_path); + if (config->dll_path == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); +} + + +static _PyInitError +get_program_name(PyCalculatePath *calculate, PyPathConfig *config) +{ + wchar_t program_name[MAXPATHLEN+1]; + memset(program_name, 0, sizeof(program_name)); + + if (GetModuleFileNameW(NULL, program_name, MAXPATHLEN)) { + goto done; } /* If there is no slash in the argv0 path, then we have to @@ -514,9 +529,10 @@ get_progpath(PyCalculatePath *calculate, PyPathConfig *config) if (wcschr(calculate->program_name, SEP)) #endif { - wcsncpy(config->program_name, calculate->program_name, MAXPATHLEN); + wcsncpy(program_name, calculate->program_name, MAXPATHLEN); } - else if (path) { + else if (calculate->path_env) { + wchar_t *path = calculate->path_env; while (1) { wchar_t *delim = wcschr(path, DELIM); @@ -524,29 +540,36 @@ get_progpath(PyCalculatePath *calculate, PyPathConfig *config) size_t len = delim - path; /* ensure we can't overwrite buffer */ len = min(MAXPATHLEN,len); - wcsncpy(config->program_name, path, len); - *(config->program_name + len) = '\0'; + wcsncpy(program_name, path, len); + program_name[len] = '\0'; } else { - wcsncpy(config->program_name, path, MAXPATHLEN); + wcsncpy(program_name, path, MAXPATHLEN); } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(config->program_name, calculate->program_name); - if (exists(config->program_name)) { + join(program_name, calculate->program_name); + if (exists(program_name)) { break; } if (!delim) { - config->program_name[0] = '\0'; + program_name[0] = '\0'; break; } path = delim + 1; } } else { - config->program_name[0] = '\0'; + program_name[0] = '\0'; } + +done: + config->program_name = _PyMem_RawWcsdup(program_name); + if (config->program_name == NULL) { + return _Py_INIT_NO_MEMORY(); + } + return _Py_INIT_OK(); } @@ -602,12 +625,13 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) } -static wchar_t* -read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite) +static int +read_pth_file(PyPathConfig *config, wchar_t *prefix, const wchar_t *path, + int *isolated, int *nosite) { FILE *sp_file = _Py_wfopen(path, L"r"); if (sp_file == NULL) { - return NULL; + return 0; } wcscpy_s(prefix, MAXPATHLEN+1, path); @@ -680,12 +704,13 @@ read_pth_file(const wchar_t *path, wchar_t *prefix, int *isolated, int *nosite) } fclose(sp_file); - return buf; + config->module_search_path = buf; + return 1; error: PyMem_RawFree(buf); fclose(sp_file); - return NULL; + return 0; } @@ -704,8 +729,8 @@ calculate_init(PyCalculatePath *calculate, static int get_pth_filename(wchar_t *spbuffer, PyPathConfig *config) { - if (config->dllpath[0]) { - if (!change_ext(spbuffer, config->dllpath, L"._pth") && exists(spbuffer)) { + if (config->dll_path[0]) { + if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { return 1; } } @@ -719,7 +744,7 @@ get_pth_filename(wchar_t *spbuffer, PyPathConfig *config) static int -calculate_pth_file(PyPathConfig *config) +calculate_pth_file(PyPathConfig *config, wchar_t *prefix) { wchar_t spbuffer[MAXPATHLEN+1]; @@ -727,13 +752,8 @@ calculate_pth_file(PyPathConfig *config) return 0; } - config->module_search_path = read_pth_file(spbuffer, config->prefix, - &Py_IsolatedFlag, - &Py_NoSiteFlag); - if (!config->module_search_path) { - return 0; - } - return 1; + return read_pth_file(config, prefix, spbuffer, + &Py_IsolatedFlag, &Py_NoSiteFlag); } @@ -775,43 +795,34 @@ calculate_pyvenv_file(PyCalculatePath *calculate) } +#define INIT_ERR_BUFFER_OVERFLOW() _Py_INIT_ERR("buffer overflow") + + static void -calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, - const _PyMainInterpreterConfig *main_config) +calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) { - get_progpath(calculate, config); - /* program_name guaranteed \0 terminated in MAXPATH+1 bytes. */ - wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_name); - reduce(calculate->argv0_path); - - /* Search for a sys.path file */ - if (calculate_pth_file(config)) { - return; - } - - calculate_pyvenv_file(calculate); - - /* Calculate zip archive path from DLL or exe path */ - change_ext(calculate->zip_path, - config->dllpath[0] ? config->dllpath : config->program_name, - L".zip"); - if (calculate->home == NULL || *calculate->home == '\0') { if (calculate->zip_path[0] && exists(calculate->zip_path)) { - wcscpy_s(config->prefix, MAXPATHLEN+1, calculate->zip_path); - reduce(config->prefix); - calculate->home = config->prefix; - } else if (search_for_prefix(config->prefix, calculate->argv0_path, LANDMARK)) { - calculate->home = config->prefix; + wcscpy_s(prefix, MAXPATHLEN+1, calculate->zip_path); + reduce(prefix); + calculate->home = prefix; + } + else if (search_for_prefix(prefix, calculate->argv0_path, LANDMARK)) { + calculate->home = prefix; } else { calculate->home = NULL; } } else { - wcscpy_s(config->prefix, MAXPATHLEN+1, calculate->home); + wcscpy_s(prefix, MAXPATHLEN+1, calculate->home); } +} + +static _PyInitError +calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config, wchar_t *prefix) +{ int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED calculate->machine_path = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome); @@ -873,34 +884,34 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, fprintf(stderr, "Using default static path.\n"); config->module_search_path = PYTHONPATH; } - return; + return _Py_INIT_OK(); } start_buf = buf; if (calculate->module_search_path_env) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->module_search_path_env)) { - Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); + return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->zip_path[0]) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->zip_path)) { - Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); + return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->user_path) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->user_path)) { - Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); + return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; } if (calculate->machine_path) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->machine_path)) { - Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); + return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; @@ -908,7 +919,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, if (calculate->home == NULL) { if (!skipdefault) { if (wcscpy_s(buf, bufsz - (buf - start_buf), PYTHONPATH)) { - Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); + return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); *buf++ = DELIM; @@ -927,7 +938,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, } if (p[0] == '.' && is_sep(p[1])) { if (wcscpy_s(buf, bufsz - (buf - start_buf), calculate->home)) { - Py_FatalError("buffer overflow in getpathp.c's calculate_path()"); + return INIT_ERR_BUFFER_OVERFLOW(); } buf = wcschr(buf, L'\0'); p++; @@ -957,7 +968,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, on the path, and that our 'prefix' directory is the parent of that. */ - if (config->prefix[0] == L'\0') { + if (prefix[0] == L'\0') { wchar_t lookBuf[MAXPATHLEN+1]; wchar_t *look = buf - 1; /* 'buf' is at the end of the buffer */ while (1) { @@ -974,7 +985,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, lookBuf[nchars] = L'\0'; /* Up one level to the parent */ reduce(lookBuf); - if (search_for_prefix(config->prefix, lookBuf, LANDMARK)) { + if (search_for_prefix(prefix, lookBuf, LANDMARK)) { break; } /* If we are out of paths to search - give up */ @@ -986,6 +997,59 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, } config->module_search_path = start_buf; + return _Py_INIT_OK(); +} + + +static _PyInitError +calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, + const _PyMainInterpreterConfig *main_config) +{ + _PyInitError err; + + err = get_dll_path(calculate, config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + err = get_program_name(calculate, config); + if (_Py_INIT_FAILED(err)) { + return err; + } + + /* program_name guaranteed \0 terminated in MAXPATH+1 bytes. */ + wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_name); + reduce(calculate->argv0_path); + + wchar_t prefix[MAXPATHLEN+1]; + memset(prefix, 0, sizeof(prefix)); + + /* Search for a sys.path file */ + if (calculate_pth_file(config, prefix)) { + goto done; + } + + calculate_pyvenv_file(calculate); + + /* Calculate zip archive path from DLL or exe path */ + change_ext(calculate->zip_path, + config->dll_path[0] ? config->dll_path : config->program_name, + L".zip"); + + calculate_home_prefix(calculate, prefix); + + err = calculate_module_search_path(calculate, config, prefix); + if (_Py_INIT_FAILED(err)) { + return err; + } + +done: + config->prefix = _PyMem_RawWcsdup(prefix); + if (config->prefix == NULL) { + return _Py_INIT_NO_MEMORY(); + } + + return _Py_INIT_OK(); } @@ -996,47 +1060,85 @@ calculate_free(PyCalculatePath *calculate) PyMem_RawFree(calculate->user_path); } + static void -calculate_path(const _PyMainInterpreterConfig *main_config) +pathconfig_clear(PyPathConfig *config) { +#define CLEAR(ATTR) \ + do { \ + PyMem_RawFree(ATTR); \ + ATTR = NULL; \ + } while (0) + + CLEAR(config->prefix); + CLEAR(config->program_name); + CLEAR(config->dll_path); + CLEAR(config->module_search_path); +#undef CLEAR +} + + +/* Initialize paths for Py_GetPath(), Py_GetPrefix(), Py_GetExecPrefix() + and Py_GetProgramFullPath() */ +_PyInitError +_PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) +{ + if (path_config.module_search_path) { + /* Already initialized */ + return _Py_INIT_OK(); + } + _PyInitError err; + PyCalculatePath calculate; memset(&calculate, 0, sizeof(calculate)); - _PyMainInterpreterConfig tmp_config; - int use_tmp = (main_config == NULL); - if (use_tmp) { - tmp_config = _PyMainInterpreterConfig_INIT; - err = _PyMainInterpreterConfig_ReadEnv(&tmp_config); - if (_Py_INIT_FAILED(err)) { - goto fatal_error; - } - main_config = &tmp_config; - } - calculate_init(&calculate, main_config); PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); - calculate_path_impl(&calculate, &new_path_config, main_config); + err = calculate_path_impl(&calculate, &new_path_config, main_config); + if (_Py_INIT_FAILED(err)) { + goto done; + } + path_config = new_path_config; + err = _Py_INIT_OK(); - if (use_tmp) { - _PyMainInterpreterConfig_Clear(&tmp_config); +done: + if (_Py_INIT_FAILED(err)) { + pathconfig_clear(&new_path_config); } calculate_free(&calculate); - return; - -fatal_error: - if (use_tmp) { - _PyMainInterpreterConfig_Clear(&tmp_config); - } - calculate_free(&calculate); - _Py_FatalInitError(err); + return err; } +static void +calculate_path(void) +{ + _PyInitError err; + _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; + + err = _PyMainInterpreterConfig_ReadEnv(&config); + if (!_Py_INIT_FAILED(err)) { + err = _PyPathConfig_Init(&config); + } + _PyMainInterpreterConfig_Clear(&config); + + if (_Py_INIT_FAILED(err)) { + _Py_FatalInitError(err); + } +} + + +void +_PyPathConfig_Fini(void) +{ + pathconfig_clear(&path_config); +} + /* External interface */ @@ -1044,31 +1146,21 @@ void Py_SetPath(const wchar_t *path) { if (path_config.module_search_path != NULL) { - PyMem_RawFree(path_config.module_search_path); - path_config.module_search_path = NULL; + pathconfig_clear(&path_config); } if (path == NULL) { return; } - wchar_t *program_name = Py_GetProgramName(); - wcsncpy(path_config.program_name, program_name, MAXPATHLEN); - path_config.prefix[0] = L'\0'; - path_config.module_search_path = PyMem_RawMalloc((wcslen(path) + 1) * sizeof(wchar_t)); - if (path_config.module_search_path != NULL) { - wcscpy(path_config.module_search_path, path); - } -} + PyPathConfig new_config; + new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + new_config.prefix = _PyMem_RawWcsdup(L""); + new_config.dll_path = _PyMem_RawWcsdup(L""); + new_config.module_search_path = _PyMem_RawWcsdup(path); - -wchar_t * -_Py_GetPathWithConfig(const _PyMainInterpreterConfig *main_config) -{ - if (!path_config.module_search_path) { - calculate_path(main_config); - } - return path_config.module_search_path; + pathconfig_clear(&path_config); + path_config = new_config; } @@ -1076,7 +1168,7 @@ wchar_t * Py_GetPath(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.module_search_path; } @@ -1086,7 +1178,7 @@ wchar_t * Py_GetPrefix(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.prefix; } @@ -1103,7 +1195,7 @@ wchar_t * Py_GetProgramFullPath(void) { if (!path_config.module_search_path) { - calculate_path(NULL); + calculate_path(); } return path_config.program_name; } @@ -1129,7 +1221,7 @@ _Py_CheckPython3() /* If there is a python3.dll next to the python3y.dll, assume this is a build tree; use that DLL */ - wcscpy(py3path, path_config.dllpath); + wcscpy(py3path, path_config.dll_path); s = wcsrchr(py3path, L'\\'); if (!s) { s = py3path; diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 714be3768f6..868ac8450d4 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -866,11 +866,6 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) /* Now finish configuring the main interpreter */ interp->config = *config; - /* GetPath may initialize state that _PySys_EndInit locks - in, and so has to be called first. */ - /* TODO: Call Py_GetPath() in Py_ReadConfig, rather than here */ - wchar_t *sys_path = _Py_GetPathWithConfig(&interp->config); - if (interp->core_config._disable_importlib) { /* Special mode for freeze_importlib: run with no import system * @@ -880,11 +875,20 @@ _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) _PyRuntime.initialized = 1; return _Py_INIT_OK(); } + /* TODO: Report exceptions rather than fatal errors below here */ if (_PyTime_Init() < 0) return _Py_INIT_ERR("can't initialize time"); + /* GetPath may initialize state that _PySys_EndInit locks + in, and so has to be called first. */ + err = _PyPathConfig_Init(&interp->config); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *sys_path = Py_GetPath(); + /* Finish setting up the sys module and import system */ PySys_SetPath(sys_path); if (_PySys_EndInit(interp->sysdict) < 0) @@ -1261,6 +1265,9 @@ Py_FinalizeEx(void) #endif call_ll_exitfuncs(); + + _PyPathConfig_Fini(); + _PyRuntime_Finalize(); return status; } @@ -1290,6 +1297,7 @@ new_interpreter(PyThreadState **tstate_p) PyInterpreterState *interp; PyThreadState *tstate, *save_tstate; PyObject *bimod, *sysmod; + _PyInitError err; if (!_PyRuntime.initialized) { return _Py_INIT_ERR("Py_Initialize must be called first"); @@ -1325,10 +1333,13 @@ new_interpreter(PyThreadState **tstate_p) interp->config = main_interp->config; } + err = _PyPathConfig_Init(&interp->config); + if (_Py_INIT_FAILED(err)) { + return err; + } + wchar_t *sys_path = Py_GetPath(); + /* XXX The following is lax in error checking */ - - wchar_t *sys_path = _Py_GetPathWithConfig(&interp->config); - PyObject *modules = PyDict_New(); if (modules == NULL) { return _Py_INIT_ERR("can't make modules dictionary"); @@ -1359,7 +1370,6 @@ new_interpreter(PyThreadState **tstate_p) if (bimod != NULL && sysmod != NULL) { PyObject *pstderr; - _PyInitError err; /* Set up a preliminary stderr printer until we have enough infrastructure for the io module in place. */