bpo-32030: Add _PyMainInterpreterConfig_ReadEnv() (#4542)

Py_GetPath() and Py_Main() now call
_PyMainInterpreterConfig_ReadEnv() to share the same code to get
environment variables.

Changes:

* Add _PyMainInterpreterConfig_ReadEnv()
* Add _PyMainInterpreterConfig_Clear()
* Add _PyMem_RawWcsdup()
* _PyMainInterpreterConfig: rename pythonhome to home
* Rename _Py_ReadMainInterpreterConfig() to
  _PyMainInterpreterConfig_Read()
* Use _Py_INIT_USER_ERR(), instead of _Py_INIT_ERR(), for decoding
  errors: the user is able to fix the issue, it's not a bug in
  Python. Same change was made in _Py_INIT_NO_MEMORY().
* Remove _Py_GetPythonHomeWithConfig()
This commit is contained in:
Victor Stinner 2017-11-24 22:55:40 +01:00 committed by GitHub
parent 84c4b1938f
commit 46972b7bc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 165 additions and 142 deletions

View file

@ -120,7 +120,6 @@ typedef struct {
wchar_t *path_env; /* PATH environment variable */
wchar_t *home; /* PYTHONHOME environment variable */
wchar_t *module_search_path_env; /* PYTHONPATH environment variable */
wchar_t *module_search_path_buffer;
wchar_t *prog; /* Program name */
wchar_t *pythonpath; /* PYTHONPATH define */
@ -886,9 +885,9 @@ calculate_module_search_path(PyCalculatePath *calculate, PyPathConfig *config)
}
#define DECODE_FAILED(NAME, LEN) \
#define DECODE_LOCALE_ERR(NAME, LEN) \
((LEN) == (size_t)-2) \
? _Py_INIT_ERR("failed to decode " #NAME) \
? _Py_INIT_USER_ERR("failed to decode " #NAME) \
: _Py_INIT_NO_MEMORY()
@ -896,19 +895,15 @@ static _PyInitError
calculate_init(PyCalculatePath *calculate,
const _PyMainInterpreterConfig *main_config)
{
_PyInitError err;
err = _Py_GetPythonHomeWithConfig(main_config, &calculate->home);
if (_Py_INIT_FAILED(err)) {
return err;
}
calculate->home = main_config->home;
calculate->module_search_path_env = main_config->module_search_path_env;
size_t len;
char *path = getenv("PATH");
if (path) {
calculate->path_env = Py_DecodeLocale(path, &len);
if (!calculate->path_env) {
return DECODE_FAILED("PATH environment variable", len);
return DECODE_LOCALE_ERR("PATH environment variable", len);
}
}
@ -916,37 +911,19 @@ calculate_init(PyCalculatePath *calculate,
calculate->pythonpath = Py_DecodeLocale(PYTHONPATH, &len);
if (!calculate->pythonpath) {
return DECODE_FAILED("PYTHONPATH define", len);
return DECODE_LOCALE_ERR("PYTHONPATH define", len);
}
calculate->prefix = Py_DecodeLocale(PREFIX, &len);
if (!calculate->prefix) {
return DECODE_FAILED("PREFIX define", len);
return DECODE_LOCALE_ERR("PREFIX define", len);
}
calculate->exec_prefix = Py_DecodeLocale(EXEC_PREFIX, &len);
if (!calculate->prefix) {
return DECODE_FAILED("EXEC_PREFIX define", len);
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
}
calculate->lib_python = Py_DecodeLocale("lib/python" VERSION, &len);
if (!calculate->lib_python) {
return DECODE_FAILED("EXEC_PREFIX define", len);
}
calculate->module_search_path_env = NULL;
if (main_config) {
if (main_config->module_search_path_env) {
calculate->module_search_path_env = main_config->module_search_path_env;
}
}
else {
char *pythonpath = Py_GETENV("PYTHONPATH");
if (pythonpath && pythonpath[0] != '\0') {
calculate->module_search_path_buffer = Py_DecodeLocale(pythonpath, &len);
if (!calculate->module_search_path_buffer) {
return DECODE_FAILED("PYTHONPATH environment variable", len);
}
calculate->module_search_path_env = calculate->module_search_path_buffer;
}
return DECODE_LOCALE_ERR("EXEC_PREFIX define", len);
}
return _Py_INIT_OK();
}
@ -960,7 +937,6 @@ calculate_free(PyCalculatePath *calculate)
PyMem_RawFree(calculate->exec_prefix);
PyMem_RawFree(calculate->lib_python);
PyMem_RawFree(calculate->path_env);
PyMem_RawFree(calculate->module_search_path_buffer);
}
@ -988,13 +964,24 @@ calculate_path_impl(PyCalculatePath *calculate, PyPathConfig *config)
static void
calculate_path(const _PyMainInterpreterConfig *main_config)
{
_PyInitError err;
PyCalculatePath calculate;
memset(&calculate, 0, sizeof(calculate));
_PyInitError err = calculate_init(&calculate, main_config);
_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);
if (_Py_INIT_FAILED(err)) {
calculate_free(&calculate);
_Py_FatalInitError(err);
goto fatal_error;
}
PyPathConfig new_path_config;
@ -1003,7 +990,18 @@ calculate_path(const _PyMainInterpreterConfig *main_config)
calculate_path_impl(&calculate, &new_path_config);
path_config = new_path_config;
if (use_tmp) {
_PyMainInterpreterConfig_Clear(&tmp_config);
}
calculate_free(&calculate);
return;
fatal_error:
if (use_tmp) {
_PyMainInterpreterConfig_Clear(&tmp_config);
}
calculate_free(&calculate);
_Py_FatalInitError(err);
}

View file

@ -36,10 +36,16 @@
extern "C" {
#endif
#define DECODE_LOCALE_ERR(NAME, LEN) \
(((LEN) == -2) \
? _Py_INIT_USER_ERR("failed to decode " #NAME) \
: _Py_INIT_NO_MEMORY())
#define SET_DECODE_ERROR(NAME, LEN) \
do { \
if ((LEN) == (size_t)-2) { \
pymain->err = _Py_INIT_ERR("failed to decode " #NAME); \
pymain->err = _Py_INIT_USER_ERR("failed to decode " #NAME); \
} \
else { \
pymain->err = _Py_INIT_NO_MEMORY(); \
@ -450,7 +456,7 @@ pymain_free_impl(_PyMain *pymain)
Py_CLEAR(pymain->main_importer_path);
PyMem_RawFree(pymain->program_name);
PyMem_RawFree(pymain->config.module_search_path_env);
_PyMainInterpreterConfig_Clear(&pymain->config);
#ifdef __INSURE__
/* Insure++ is a memory analysis tool that aids in discovering
@ -515,20 +521,11 @@ error:
static wchar_t*
pymain_wstrdup(_PyMain *pymain, wchar_t *str)
{
size_t len = wcslen(str) + 1; /* +1 for NUL character */
if (len > (size_t)PY_SSIZE_T_MAX / sizeof(wchar_t)) {
pymain->err = _Py_INIT_NO_MEMORY();
return NULL;
}
size_t size = len * sizeof(wchar_t);
wchar_t *str2 = PyMem_RawMalloc(size);
wchar_t *str2 = _PyMem_RawWcsdup(str);
if (str2 == NULL) {
pymain->err = _Py_INIT_NO_MEMORY();
return NULL;
}
memcpy(str2, str, size);
return str2;
}
@ -955,7 +952,7 @@ pymain_init_main_interpreter(_PyMain *pymain)
_PyInitError err;
/* TODO: Print any exceptions raised by these operations */
err = _Py_ReadMainInterpreterConfig(&pymain->config);
err = _PyMainInterpreterConfig_Read(&pymain->config);
if (_Py_INIT_FAILED(err)) {
pymain->err = err;
return -1;
@ -1361,8 +1358,7 @@ pymain_set_flags_from_env(_PyMain *pymain)
static int
pymain_get_env_var_dup(_PyMain *pymain, wchar_t **dest,
wchar_t *wname, char *name)
config_get_env_var_dup(wchar_t **dest, wchar_t *wname, char *name)
{
if (Py_IgnoreEnvironmentFlag) {
*dest = NULL;
@ -1376,7 +1372,7 @@ pymain_get_env_var_dup(_PyMain *pymain, wchar_t **dest,
return 0;
}
wchar_t *copy = pymain_wstrdup(pymain, var);
wchar_t *copy = _PyMem_RawWcsdup(var);
if (copy == NULL) {
return -1;
}
@ -1393,11 +1389,9 @@ pymain_get_env_var_dup(_PyMain *pymain, wchar_t **dest,
wchar_t *wvar = Py_DecodeLocale(var, &len);
if (!wvar) {
if (len == (size_t)-2) {
/* don't set pymain->err */
return -2;
}
else {
pymain->err = _Py_INIT_NO_MEMORY();
return -1;
}
}
@ -1407,25 +1401,21 @@ pymain_get_env_var_dup(_PyMain *pymain, wchar_t **dest,
}
static int
pymain_init_pythonpath(_PyMain *pymain)
static _PyInitError
config_init_pythonpath(_PyMainInterpreterConfig *config)
{
wchar_t *path;
int res = pymain_get_env_var_dup(pymain, &path,
L"PYTHONPATH", "PYTHONPATH");
int res = config_get_env_var_dup(&path, L"PYTHONPATH", "PYTHONPATH");
if (res < 0) {
if (res == -2) {
SET_DECODE_ERROR("PYTHONPATH", (size_t)-2);
}
return -1;
return DECODE_LOCALE_ERR("PYTHONHOME", res);
}
pymain->config.module_search_path_env = path;
return 0;
config->module_search_path_env = path;
return _Py_INIT_OK();
}
static int
pymain_init_pythonhome(_PyMain *pymain)
static _PyInitError
config_init_pythonhome(_PyMainInterpreterConfig *config)
{
wchar_t *home;
@ -1433,26 +1423,41 @@ pymain_init_pythonhome(_PyMain *pymain)
if (home) {
/* Py_SetPythonHome() has been called before Py_Main(),
use its value */
pymain->config.pythonhome = pymain_wstrdup(pymain, home);
if (pymain->config.pythonhome == NULL) {
return -1;
config->home = _PyMem_RawWcsdup(home);
if (config->home == NULL) {
return _Py_INIT_NO_MEMORY();
}
return 0;
return _Py_INIT_OK();
}
int res = pymain_get_env_var_dup(pymain, &home,
L"PYTHONHOME", "PYTHONHOME");
int res = config_get_env_var_dup(&home, L"PYTHONHOME", "PYTHONHOME");
if (res < 0) {
if (res == -2) {
SET_DECODE_ERROR("PYTHONHOME", (size_t)-2);
}
return -1;
return DECODE_LOCALE_ERR("PYTHONHOME", res);
}
pymain->config.pythonhome = home;
return 0;
config->home = home;
return _Py_INIT_OK();
}
_PyInitError
_PyMainInterpreterConfig_ReadEnv(_PyMainInterpreterConfig *config)
{
_PyInitError err = config_init_pythonhome(config);
if (_Py_INIT_FAILED(err)) {
return err;
}
err = config_init_pythonpath(config);
if (_Py_INIT_FAILED(err)) {
return err;
}
return _Py_INIT_OK();
}
static int
pymain_parse_envvars(_PyMain *pymain)
{
@ -1474,10 +1479,10 @@ pymain_parse_envvars(_PyMain *pymain)
return -1;
}
core_config->allocator = Py_GETENV("PYTHONMALLOC");
if (pymain_init_pythonpath(pymain) < 0) {
return -1;
}
if (pymain_init_pythonhome(pymain) < 0) {
_PyInitError err = _PyMainInterpreterConfig_ReadEnv(&pymain->config);
if (_Py_INIT_FAILED(pymain->err)) {
pymain->err = err;
return -1;
}