diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h index 7056e105ff7..50ad2fc83a3 100644 --- a/Include/internal/pystate.h +++ b/Include/internal/pystate.h @@ -37,6 +37,22 @@ struct _gilstate_runtime_state { #define _PyGILState_check_enabled _PyRuntime.gilstate.check_enabled +typedef struct { + /* Full path to the Python program */ + wchar_t *program_full_path; + wchar_t *prefix; +#ifdef MS_WINDOWS + wchar_t *dll_path; +#else + wchar_t *exec_prefix; +#endif + /* Set by Py_SetPath(), or computed by _PyPathConfig_Init() */ + wchar_t *module_search_path; +} _PyPathConfig; + +#define _PyPathConfig_INIT {.module_search_path = NULL} + + /* Full Python runtime state */ typedef struct pyruntimestate { diff --git a/Modules/getpath.c b/Modules/getpath.c index 02d626cea73..9f5e8b3ff5c 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -1,6 +1,7 @@ /* Return the initial module search path. */ #include "Python.h" +#include "internal/pystate.h" #include "osdefs.h" #include @@ -114,14 +115,6 @@ extern "C" { ? _Py_INIT_USER_ERR("cannot decode " #NAME) \ : _Py_INIT_NO_MEMORY() - -typedef struct { - wchar_t *prefix; - wchar_t *exec_prefix; - wchar_t *program_name; - wchar_t *module_search_path; -} PyPathConfig; - typedef struct { wchar_t *path_env; /* PATH environment variable */ wchar_t *home; /* PYTHONHOME environment variable */ @@ -142,7 +135,7 @@ typedef struct { static const wchar_t delimiter[2] = {DELIM, '\0'}; static const wchar_t separator[2] = {SEP, '\0'}; -static PyPathConfig path_config = {.module_search_path = NULL}; +static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* Get file status. Encode the path to the locale encoding. */ @@ -592,10 +585,10 @@ calculate_reduce_exec_prefix(PyCalculatePath *calculate, wchar_t *exec_prefix) static _PyInitError -calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) +calculate_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) { - wchar_t program_name[MAXPATHLEN+1]; - memset(program_name, 0, sizeof(program_name)); + wchar_t program_full_path[MAXPATHLEN+1]; + memset(program_full_path, 0, sizeof(program_full_path)); #ifdef __APPLE__ #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 @@ -612,7 +605,7 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) * $PATH isn't exported, you lose. */ if (wcschr(calculate->program_name, SEP)) { - wcsncpy(program_name, calculate->program_name, MAXPATHLEN); + wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); } #ifdef __APPLE__ /* On Mac OS X, if a script uses an interpreter of the form @@ -628,10 +621,10 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) else if(0 == _NSGetExecutablePath(execpath, &nsexeclength) && execpath[0] == SEP) { - size_t r = mbstowcs(program_name, execpath, MAXPATHLEN+1); + size_t r = mbstowcs(program_full_path, execpath, MAXPATHLEN+1); if (r == (size_t)-1 || r > MAXPATHLEN) { /* Could not convert execpath, or it's too long. */ - program_name[0] = '\0'; + program_full_path[0] = '\0'; } } #endif /* __APPLE__ */ @@ -645,34 +638,34 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) if (len > MAXPATHLEN) { len = MAXPATHLEN; } - wcsncpy(program_name, path, len); - program_name[len] = '\0'; + wcsncpy(program_full_path, path, len); + program_full_path[len] = '\0'; } else { - wcsncpy(program_name, path, MAXPATHLEN); + wcsncpy(program_full_path, path, MAXPATHLEN); } - joinpath(program_name, calculate->program_name); - if (isxfile(program_name)) { + joinpath(program_full_path, calculate->program_name); + if (isxfile(program_full_path)) { break; } if (!delim) { - program_name[0] = L'\0'; + program_full_path[0] = L'\0'; break; } path = delim + 1; } } else { - program_name[0] = '\0'; + program_full_path[0] = '\0'; } - if (program_name[0] != SEP && program_name[0] != '\0') { - absolutize(program_name); + if (program_full_path[0] != SEP && program_full_path[0] != '\0') { + absolutize(program_full_path); } - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { + config->program_full_path = _PyMem_RawWcsdup(program_full_path); + if (config->program_full_path == NULL) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -680,9 +673,9 @@ calculate_program_name(PyCalculatePath *calculate, PyPathConfig *config) static _PyInitError -calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) +calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_full_path) { - wcsncpy(calculate->argv0_path, program_name, MAXPATHLEN); + wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN); calculate->argv0_path[MAXPATHLEN] = '\0'; #ifdef WITH_NEXT_FRAMEWORK @@ -718,10 +711,10 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) 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, program_name, MAXPATHLEN); + wcsncpy(calculate->argv0_path, program_full_path, MAXPATHLEN); } else { - /* Use the location of the library as the program_name */ + /* Use the location of the library as the program_full_path */ wcsncpy(calculate->argv0_path, wbuf, MAXPATHLEN); } PyMem_RawFree(wbuf); @@ -730,7 +723,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) #if HAVE_READLINK wchar_t tmpbuffer[MAXPATHLEN+1]; - int linklen = _Py_wreadlink(program_name, tmpbuffer, MAXPATHLEN); + int linklen = _Py_wreadlink(program_full_path, tmpbuffer, MAXPATHLEN); while (linklen != -1) { if (tmpbuffer[0] == SEP) { /* tmpbuffer should never be longer than MAXPATHLEN, @@ -738,7 +731,7 @@ calculate_argv0_path(PyCalculatePath *calculate, const wchar_t *program_name) wcsncpy(calculate->argv0_path, tmpbuffer, MAXPATHLEN); } else { - /* Interpret relative to program_name */ + /* Interpret relative to program_full_path */ reduce(calculate->argv0_path); joinpath(calculate->argv0_path, tmpbuffer); } @@ -819,7 +812,7 @@ calculate_zip_path(PyCalculatePath *calculate, const wchar_t *prefix) static _PyInitError calculate_module_search_path(PyCalculatePath *calculate, const wchar_t *prefix, const wchar_t *exec_prefix, - PyPathConfig *config) + _PyPathConfig *config) { /* Calculate size of return buffer */ size_t bufsz = 0; @@ -955,14 +948,14 @@ calculate_free(PyCalculatePath *calculate) static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config) +calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config) { - _PyInitError err = calculate_program_name(calculate, config); + _PyInitError err = calculate_program_full_path(calculate, config); if (_Py_INIT_FAILED(err)) { return err; } - err = calculate_argv0_path(calculate, config->program_name); + err = calculate_argv0_path(calculate, config->program_full_path); if (_Py_INIT_FAILED(err)) { return err; } @@ -1011,7 +1004,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config) static void -pathconfig_clear(PyPathConfig *config) +pathconfig_clear(_PyPathConfig *config) { #define CLEAR(ATTR) \ do { \ @@ -1021,7 +1014,7 @@ pathconfig_clear(PyPathConfig *config) CLEAR(config->prefix); CLEAR(config->exec_prefix); - CLEAR(config->program_name); + CLEAR(config->program_full_path); CLEAR(config->module_search_path); #undef CLEAR } @@ -1032,7 +1025,7 @@ pathconfig_clear(PyPathConfig *config) _PyInitError _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { - if (path_config.module_search_path) { + if (_Py_path_config.module_search_path) { /* Already initialized */ return _Py_INIT_OK(); } @@ -1045,7 +1038,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - PyPathConfig new_path_config; + _PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); err = calculate_path_impl(&calculate, &new_path_config); @@ -1054,7 +1047,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - path_config = new_path_config; + _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: @@ -1064,8 +1057,13 @@ done: static void -calculate_path(void) +pathconfig_global_init(void) { + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + _PyInitError err; _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; @@ -1084,7 +1082,7 @@ calculate_path(void) void _PyPathConfig_Fini(void) { - pathconfig_clear(&path_config); + pathconfig_clear(&_Py_path_config); } @@ -1093,58 +1091,50 @@ void Py_SetPath(const wchar_t *path) { if (path == NULL) { - pathconfig_clear(&path_config); + pathconfig_clear(&_Py_path_config); return; } - PyPathConfig new_config; - new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + _PyPathConfig new_config; + new_config.program_full_path = _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); - pathconfig_clear(&path_config); - path_config = new_config; + pathconfig_clear(&_Py_path_config); + _Py_path_config = new_config; } wchar_t * Py_GetPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.module_search_path; + pathconfig_global_init(); + return _Py_path_config.module_search_path; } wchar_t * Py_GetPrefix(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.prefix; + pathconfig_global_init(); + return _Py_path_config.prefix; } wchar_t * Py_GetExecPrefix(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.exec_prefix; + pathconfig_global_init(); + return _Py_path_config.exec_prefix; } wchar_t * Py_GetProgramFullPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.program_name; + pathconfig_global_init(); + return _Py_path_config.program_full_path; } #ifdef __cplusplus diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c index 4d85f0c368b..7911028ad83 100644 --- a/Objects/obmalloc.c +++ b/Objects/obmalloc.c @@ -564,6 +564,8 @@ PyMem_Free(void *ptr) wchar_t* _PyMem_RawWcsdup(const wchar_t *str) { + assert(str != NULL); + size_t len = wcslen(str); if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t) - 1) { return NULL; @@ -582,13 +584,12 @@ _PyMem_RawWcsdup(const wchar_t *str) char * _PyMem_RawStrdup(const char *str) { - size_t size; - char *copy; - - size = strlen(str) + 1; - copy = PyMem_RawMalloc(size); - if (copy == NULL) + assert(str != NULL); + size_t size = strlen(str) + 1; + char *copy = PyMem_RawMalloc(size); + if (copy == NULL) { return NULL; + } memcpy(copy, str, size); return copy; } @@ -596,13 +597,12 @@ _PyMem_RawStrdup(const char *str) char * _PyMem_Strdup(const char *str) { - size_t size; - char *copy; - - size = strlen(str) + 1; - copy = PyMem_Malloc(size); - if (copy == NULL) + assert(str != NULL); + size_t size = strlen(str) + 1; + char *copy = PyMem_Malloc(size); + if (copy == NULL) { return NULL; + } memcpy(copy, str, size); return copy; } diff --git a/PC/getpathp.c b/PC/getpathp.c index fe0226ba5d2..ad04b6b6efc 100644 --- a/PC/getpathp.c +++ b/PC/getpathp.c @@ -80,6 +80,7 @@ #include "Python.h" +#include "internal/pystate.h" #include "osdefs.h" #include @@ -116,13 +117,6 @@ #define LANDMARK L"lib\\os.py" #endif -typedef struct { - wchar_t *prefix; - wchar_t *program_name; - wchar_t *dll_path; - wchar_t *module_search_path; -} PyPathConfig; - typedef struct { wchar_t *module_search_path_env; /* PYTHONPATH environment variable */ wchar_t *path_env; /* PATH environment variable */ @@ -138,7 +132,7 @@ typedef struct { } PyCalculatePath; -static PyPathConfig path_config = {.module_search_path = NULL}; +static _PyPathConfig _Py_path_config = _PyPathConfig_INIT; /* determine if "ch" is a separator character */ @@ -295,7 +289,7 @@ gotlandmark(wchar_t *prefix, const wchar_t *landmark) /* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd. - assumption provided by only caller, calculate_path() */ + assumption provided by only caller, calculate_path_impl() */ static int search_for_prefix(wchar_t *prefix, wchar_t *argv0_path, const wchar_t *landmark) { @@ -484,7 +478,7 @@ done: static _PyInitError -get_dll_path(PyCalculatePath *calculate, PyPathConfig *config) +get_dll_path(PyCalculatePath *calculate, _PyPathConfig *config) { wchar_t dll_path[MAXPATHLEN+1]; memset(dll_path, 0, sizeof(dll_path)); @@ -509,12 +503,12 @@ get_dll_path(PyCalculatePath *calculate, PyPathConfig *config) static _PyInitError -get_program_name(PyCalculatePath *calculate, PyPathConfig *config) +get_program_full_path(PyCalculatePath *calculate, _PyPathConfig *config) { - wchar_t program_name[MAXPATHLEN+1]; - memset(program_name, 0, sizeof(program_name)); + wchar_t program_full_path[MAXPATHLEN+1]; + memset(program_full_path, 0, sizeof(program_full_path)); - if (GetModuleFileNameW(NULL, program_name, MAXPATHLEN)) { + if (GetModuleFileNameW(NULL, program_full_path, MAXPATHLEN)) { goto done; } @@ -529,7 +523,7 @@ get_program_name(PyCalculatePath *calculate, PyPathConfig *config) if (wcschr(calculate->program_name, SEP)) #endif { - wcsncpy(program_name, calculate->program_name, MAXPATHLEN); + wcsncpy(program_full_path, calculate->program_name, MAXPATHLEN); } else if (calculate->path_env) { wchar_t *path = calculate->path_env; @@ -540,33 +534,33 @@ get_program_name(PyCalculatePath *calculate, PyPathConfig *config) size_t len = delim - path; /* ensure we can't overwrite buffer */ len = min(MAXPATHLEN,len); - wcsncpy(program_name, path, len); - program_name[len] = '\0'; + wcsncpy(program_full_path, path, len); + program_full_path[len] = '\0'; } else { - wcsncpy(program_name, path, MAXPATHLEN); + wcsncpy(program_full_path, path, MAXPATHLEN); } /* join() is safe for MAXPATHLEN+1 size buffer */ - join(program_name, calculate->program_name); - if (exists(program_name)) { + join(program_full_path, calculate->program_name); + if (exists(program_full_path)) { break; } if (!delim) { - program_name[0] = '\0'; + program_full_path[0] = '\0'; break; } path = delim + 1; } } else { - program_name[0] = '\0'; + program_full_path[0] = '\0'; } done: - config->program_name = _PyMem_RawWcsdup(program_name); - if (config->program_name == NULL) { + config->program_full_path = _PyMem_RawWcsdup(program_full_path); + if (config->program_full_path == NULL) { return _Py_INIT_NO_MEMORY(); } return _Py_INIT_OK(); @@ -626,7 +620,7 @@ find_env_config_value(FILE * env_file, const wchar_t * key, wchar_t * value) static int -read_pth_file(PyPathConfig *config, wchar_t *prefix, const wchar_t *path, +read_pth_file(_PyPathConfig *config, wchar_t *prefix, const wchar_t *path, int *isolated, int *nosite) { FILE *sp_file = _Py_wfopen(path, L"r"); @@ -727,15 +721,15 @@ calculate_init(PyCalculatePath *calculate, static int -get_pth_filename(wchar_t *spbuffer, PyPathConfig *config) +get_pth_filename(wchar_t *spbuffer, _PyPathConfig *config) { if (config->dll_path[0]) { if (!change_ext(spbuffer, config->dll_path, L"._pth") && exists(spbuffer)) { return 1; } } - if (config->program_name[0]) { - if (!change_ext(spbuffer, config->program_name, L"._pth") && exists(spbuffer)) { + if (config->program_full_path[0]) { + if (!change_ext(spbuffer, config->program_full_path, L"._pth") && exists(spbuffer)) { return 1; } } @@ -744,7 +738,7 @@ get_pth_filename(wchar_t *spbuffer, PyPathConfig *config) static int -calculate_pth_file(PyPathConfig *config, wchar_t *prefix) +calculate_pth_file(_PyPathConfig *config, wchar_t *prefix) { wchar_t spbuffer[MAXPATHLEN+1]; @@ -821,7 +815,7 @@ calculate_home_prefix(PyCalculatePath *calculate, wchar_t *prefix) static _PyInitError -calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config, wchar_t *prefix) +calculate_module_search_path(PyCalculatePath *calculate, _PyPathConfig *config, wchar_t *prefix) { int skiphome = calculate->home==NULL ? 0 : 1; #ifdef Py_ENABLE_SHARED @@ -1002,7 +996,7 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config, w static _PyInitError -calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, +calculate_path_impl(PyCalculatePath *calculate, _PyPathConfig *config, const _PyMainInterpreterConfig *main_config) { _PyInitError err; @@ -1012,13 +1006,13 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, return err; } - err = get_program_name(calculate, config); + err = get_program_full_path(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); + /* program_full_path guaranteed \0 terminated in MAXPATH+1 bytes. */ + wcscpy_s(calculate->argv0_path, MAXPATHLEN+1, config->program_full_path); reduce(calculate->argv0_path); wchar_t prefix[MAXPATHLEN+1]; @@ -1033,7 +1027,7 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config, /* Calculate zip archive path from DLL or exe path */ change_ext(calculate->zip_path, - config->dll_path[0] ? config->dll_path : config->program_name, + config->dll_path[0] ? config->dll_path : config->program_full_path, L".zip"); calculate_home_prefix(calculate, prefix); @@ -1062,7 +1056,7 @@ calculate_free(PyCalculatePath *calculate) static void -pathconfig_clear(PyPathConfig *config) +pathconfig_clear(_PyPathConfig *config) { #define CLEAR(ATTR) \ do { \ @@ -1071,7 +1065,7 @@ pathconfig_clear(PyPathConfig *config) } while (0) CLEAR(config->prefix); - CLEAR(config->program_name); + CLEAR(config->program_full_path); CLEAR(config->dll_path); CLEAR(config->module_search_path); #undef CLEAR @@ -1083,7 +1077,7 @@ pathconfig_clear(PyPathConfig *config) _PyInitError _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) { - if (path_config.module_search_path) { + if (_Py_path_config.module_search_path) { /* Already initialized */ return _Py_INIT_OK(); } @@ -1095,7 +1089,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) calculate_init(&calculate, main_config); - PyPathConfig new_path_config; + _PyPathConfig new_path_config; memset(&new_path_config, 0, sizeof(new_path_config)); err = calculate_path_impl(&calculate, &new_path_config, main_config); @@ -1103,7 +1097,7 @@ _PyPathConfig_Init(const _PyMainInterpreterConfig *main_config) goto done; } - path_config = new_path_config; + _Py_path_config = new_path_config; err = _Py_INIT_OK(); done: @@ -1116,8 +1110,13 @@ done: static void -calculate_path(void) +pathconfig_global_init(void) { + if (_Py_path_config.module_search_path) { + /* Already initialized */ + return; + } + _PyInitError err; _PyMainInterpreterConfig config = _PyMainInterpreterConfig_INIT; @@ -1136,7 +1135,7 @@ calculate_path(void) void _PyPathConfig_Fini(void) { - pathconfig_clear(&path_config); + pathconfig_clear(&_Py_path_config); } @@ -1145,42 +1144,38 @@ _PyPathConfig_Fini(void) void Py_SetPath(const wchar_t *path) { - if (path_config.module_search_path != NULL) { - pathconfig_clear(&path_config); + if (_Py_path_config.module_search_path != NULL) { + pathconfig_clear(&_Py_path_config); } if (path == NULL) { return; } - PyPathConfig new_config; - new_config.program_name = _PyMem_RawWcsdup(Py_GetProgramName()); + _PyPathConfig new_config; + new_config.program_full_path = _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); - pathconfig_clear(&path_config); - path_config = new_config; + pathconfig_clear(&_Py_path_config); + _Py_path_config = new_config; } wchar_t * Py_GetPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.module_search_path; + pathconfig_global_init(); + return _Py_path_config.module_search_path; } wchar_t * Py_GetPrefix(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.prefix; + pathconfig_global_init(); + return _Py_path_config.prefix; } @@ -1194,10 +1189,8 @@ Py_GetExecPrefix(void) wchar_t * Py_GetProgramFullPath(void) { - if (!path_config.module_search_path) { - calculate_path(); - } - return path_config.program_name; + pathconfig_global_init(); + return _Py_path_config.program_full_path; } @@ -1221,7 +1214,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.dll_path); + wcscpy(py3path, _Py_path_config.dll_path); s = wcsrchr(py3path, L'\\'); if (!s) { s = py3path;