bpo-34170: Enhance _PyCoreConfig_Read() (GH-8468)

* Inline cmdline_get_env_flags() into config_read_env_vars():
  _PyCoreConfig_Read() now reads much more environment variables like
  PYTHONVERBOSE.
* Allow to override faulthandler and allocator even if dev_mode=1.
  PYTHONMALLOC is now the priority over PYTHONDEVMODE.
* Fix _PyCoreConfig_Copy(): copy also install_signal_handlers,
  coerce_c_locale and coerce_c_locale_warn
* _PyCoreConfig.install_signal_handlers default is now 1: install
  signals by default
* Fix also a compiler warning: don't define _PyPathConfig type twice.
This commit is contained in:
Victor Stinner 2018-07-26 02:37:22 +02:00 committed by GitHub
parent 48ed88a93b
commit ecf411c59e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 77 deletions

View File

@ -127,10 +127,9 @@ PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
PyAPI_FUNC(wchar_t *) Py_GetPath(void); PyAPI_FUNC(wchar_t *) Py_GetPath(void);
#ifdef Py_BUILD_CORE #ifdef Py_BUILD_CORE
struct _PyPathConfig; struct _PyPathConfig;
typedef struct _PyPathConfig _PyPathConfig;
PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal( PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal(
const _PyPathConfig *config); const struct _PyPathConfig *config);
PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv); PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv);
PyAPI_FUNC(int) _Py_FindEnvConfigValue( PyAPI_FUNC(int) _Py_FindEnvConfigValue(
FILE *env_file, FILE *env_file,

View File

@ -26,15 +26,23 @@ typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
typedef struct { typedef struct {
int install_signal_handlers; /* Install signal handlers? -1 means unset */ /* Install signal handlers? Yes by default. */
int install_signal_handlers;
int ignore_environment; /* -E, Py_IgnoreEnvironmentFlag, -1 means unset */ int ignore_environment; /* -E, Py_IgnoreEnvironmentFlag, -1 means unset */
int use_hash_seed; /* PYTHONHASHSEED=x */ int use_hash_seed; /* PYTHONHASHSEED=x */
unsigned long hash_seed; unsigned long hash_seed;
const char *allocator; /* Memory allocator: _PyMem_SetupAllocators() */ const char *allocator; /* Memory allocator: PYTHONMALLOC */
int dev_mode; /* PYTHONDEVMODE, -X dev */ int dev_mode; /* PYTHONDEVMODE, -X dev */
int faulthandler; /* PYTHONFAULTHANDLER, -X faulthandler */
int tracemalloc; /* PYTHONTRACEMALLOC, -X tracemalloc=N */ /* Enable faulthandler?
Set to 1 by -X faulthandler and PYTHONFAULTHANDLER. -1 means unset. */
int faulthandler;
/* Enable tracemalloc?
Set by -X tracemalloc=N and PYTHONTRACEMALLOC. -1 means unset */
int tracemalloc;
int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */ int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */
int show_ref_count; /* -X showrefcount */ int show_ref_count; /* -X showrefcount */
int show_alloc_count; /* -X showalloccount */ int show_alloc_count; /* -X showalloccount */
@ -229,9 +237,10 @@ typedef struct {
#define _PyCoreConfig_INIT \ #define _PyCoreConfig_INIT \
(_PyCoreConfig){ \ (_PyCoreConfig){ \
.install_signal_handlers = -1, \ .install_signal_handlers = 1, \
.ignore_environment = -1, \ .ignore_environment = -1, \
.use_hash_seed = -1, \ .use_hash_seed = -1, \
.faulthandler = -1, \
.tracemalloc = -1, \ .tracemalloc = -1, \
.coerce_c_locale = -1, \ .coerce_c_locale = -1, \
.utf8_mode = -1, \ .utf8_mode = -1, \

View File

@ -551,9 +551,7 @@ class CmdLineTest(unittest.TestCase):
env = dict(os.environ) env = dict(os.environ)
env.pop('PYTHONWARNINGS', None) env.pop('PYTHONWARNINGS', None)
env.pop('PYTHONDEVMODE', None) env.pop('PYTHONDEVMODE', None)
# Force malloc() to disable the debug hooks which are enabled env.pop('PYTHONMALLOC', None)
# by default for Python compiled in debug mode
env['PYTHONMALLOC'] = 'malloc'
if xdev: if xdev:
args = (sys.executable, '-X', 'dev', *args) args = (sys.executable, '-X', 'dev', *args)

View File

@ -0,0 +1,2 @@
-X dev: it is now possible to override the memory allocator using
PYTHONMALLOC even if the developer mode is enabled.

View File

@ -701,6 +701,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
config->LEN = config2->LEN; \ config->LEN = config2->LEN; \
} while (0) } while (0)
COPY_ATTR(install_signal_handlers);
COPY_ATTR(ignore_environment); COPY_ATTR(ignore_environment);
COPY_ATTR(use_hash_seed); COPY_ATTR(use_hash_seed);
COPY_ATTR(hash_seed); COPY_ATTR(hash_seed);
@ -714,6 +715,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
COPY_ATTR(show_alloc_count); COPY_ATTR(show_alloc_count);
COPY_ATTR(dump_refs); COPY_ATTR(dump_refs);
COPY_ATTR(malloc_stats); COPY_ATTR(malloc_stats);
COPY_ATTR(coerce_c_locale);
COPY_ATTR(coerce_c_locale_warn);
COPY_ATTR(utf8_mode); COPY_ATTR(utf8_mode);
COPY_STR_ATTR(pycache_prefix); COPY_STR_ATTR(pycache_prefix);
@ -1244,9 +1248,7 @@ config_init_warnoptions(_PyCoreConfig *config, _PyCmdline *cmdline)
static _PyInitError static _PyInitError
cmdline_init_env_warnoptions(_PyMain *pymain, _PyCoreConfig *config, _PyCmdline *cmdline) cmdline_init_env_warnoptions(_PyMain *pymain, _PyCoreConfig *config, _PyCmdline *cmdline)
{ {
if (config->ignore_environment) { assert(!config->ignore_environment);
return _Py_INIT_OK();
}
wchar_t *env; wchar_t *env;
int res = config_get_env_var_dup(config, &env, int res = config_get_env_var_dup(config, &env,
@ -1819,37 +1821,6 @@ get_env_flag(_PyCoreConfig *config, int *flag, const char *name)
} }
static void
cmdline_get_env_flags(_PyMain *pymain, _PyCoreConfig *config,
_PyCmdline *cmdline)
{
get_env_flag(config, &config->debug, "PYTHONDEBUG");
get_env_flag(config, &config->verbose, "PYTHONVERBOSE");
get_env_flag(config, &config->optimization_level, "PYTHONOPTIMIZE");
get_env_flag(config, &config->inspect, "PYTHONINSPECT");
int dont_write_bytecode = 0;
get_env_flag(config, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
if (dont_write_bytecode) {
config->write_bytecode = 0;
}
int no_user_site_directory = 0;
get_env_flag(config, &no_user_site_directory, "PYTHONNOUSERSITE");
if (no_user_site_directory) {
config->user_site_directory = 0;
}
get_env_flag(config, &config->unbuffered_stdio, "PYTHONUNBUFFERED");
#ifdef MS_WINDOWS
get_env_flag(config, &config->legacy_windows_fs_encoding,
"PYTHONLEGACYWINDOWSFSENCODING");
get_env_flag(config, &config->legacy_windows_stdio,
"PYTHONLEGACYWINDOWSSTDIO");
#endif
}
static _PyInitError static _PyInitError
config_init_home(_PyCoreConfig *config) config_init_home(_PyCoreConfig *config)
{ {
@ -1944,7 +1915,37 @@ config_init_utf8_mode(_PyCoreConfig *config)
static _PyInitError static _PyInitError
config_read_env_vars(_PyCoreConfig *config) config_read_env_vars(_PyCoreConfig *config)
{ {
assert(!config->ignore_environment);
/* Get environment variables */
get_env_flag(config, &config->debug, "PYTHONDEBUG");
get_env_flag(config, &config->verbose, "PYTHONVERBOSE");
get_env_flag(config, &config->optimization_level, "PYTHONOPTIMIZE");
get_env_flag(config, &config->inspect, "PYTHONINSPECT");
int dont_write_bytecode = 0;
get_env_flag(config, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
if (dont_write_bytecode) {
config->write_bytecode = 0;
}
int no_user_site_directory = 0;
get_env_flag(config, &no_user_site_directory, "PYTHONNOUSERSITE");
if (no_user_site_directory) {
config->user_site_directory = 0;
}
get_env_flag(config, &config->unbuffered_stdio, "PYTHONUNBUFFERED");
#ifdef MS_WINDOWS
get_env_flag(config, &config->legacy_windows_fs_encoding,
"PYTHONLEGACYWINDOWSFSENCODING");
get_env_flag(config, &config->legacy_windows_stdio,
"PYTHONLEGACYWINDOWSSTDIO");
#endif
if (config->allocator == NULL) {
config->allocator = config_get_env_var(config, "PYTHONMALLOC"); config->allocator = config_get_env_var(config, "PYTHONMALLOC");
}
if (config_get_env_var(config, "PYTHONDUMPREFS")) { if (config_get_env_var(config, "PYTHONDUMPREFS")) {
config->dump_refs = 1; config->dump_refs = 1;
@ -1998,8 +1999,6 @@ config_read_complex_options(_PyCoreConfig *config)
config_get_env_var(config, "PYTHONDEVMODE")) config_get_env_var(config, "PYTHONDEVMODE"))
{ {
config->dev_mode = 1; config->dev_mode = 1;
config->faulthandler = 1;
config->allocator = "debug";
} }
_PyInitError err = pymain_init_tracemalloc(config); _PyInitError err = pymain_init_tracemalloc(config);
@ -2033,23 +2032,17 @@ pymain_read_conf_impl(_PyMain *pymain, _PyCoreConfig *config,
return res; return res;
} }
/* Get environment variables */ if (pymain_init_core_argv(pymain, config, cmdline) < 0) {
cmdline_get_env_flags(pymain, config, cmdline); return -1;
}
assert(config->ignore_environment >= 0);
if (!config->ignore_environment) {
err = cmdline_init_env_warnoptions(pymain, config, cmdline); err = cmdline_init_env_warnoptions(pymain, config, cmdline);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
pymain->err = err; pymain->err = err;
return -1; return -1;
} }
#ifdef MS_WINDOWS
if (config->legacy_windows_fs_encoding) {
config->utf8_mode = 0;
}
#endif
if (pymain_init_core_argv(pymain, config, cmdline) < 0) {
return -1;
} }
err = _PyCoreConfig_Read(config); err = _PyCoreConfig_Read(config);
@ -2186,14 +2179,6 @@ config_init_locale(_PyCoreConfig *config)
} }
return; return;
} }
/* By default, C locale coercion and UTF-8 Mode are disabled */
if (config->coerce_c_locale < 0) {
config->coerce_c_locale = 0;
}
if (config->utf8_mode < 0) {
config->utf8_mode = 0;
}
} }
@ -2216,10 +2201,13 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
_PyCoreConfig_GetGlobalConfig(config); _PyCoreConfig_GetGlobalConfig(config);
assert(config->ignore_environment >= 0);
if (!config->ignore_environment) {
err = config_read_env_vars(config); err = config_read_env_vars(config);
if (_Py_INIT_FAILED(err)) { if (_Py_INIT_FAILED(err)) {
return err; return err;
} }
}
/* -X options */ /* -X options */
if (config_get_xoption(config, L"showrefcount")) { if (config_get_xoption(config, L"showrefcount")) {
@ -2260,13 +2248,38 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
} }
} }
/* options side effects */
if (config->dev_mode) {
if (config->faulthandler < 0) {
config->faulthandler = 1;
}
if (config->allocator == NULL) {
config->allocator = "debug";
}
}
#ifdef MS_WINDOWS
if (config->legacy_windows_fs_encoding) {
config->utf8_mode = 0;
}
#endif
/* default values */ /* default values */
if (config->use_hash_seed < 0) {
config->use_hash_seed = 0;
config->hash_seed = 0;
}
if (config->faulthandler < 0) {
config->faulthandler = 0;
}
if (config->tracemalloc < 0) { if (config->tracemalloc < 0) {
config->tracemalloc = 0; config->tracemalloc = 0;
} }
if (config->install_signal_handlers < 0) { if (config->coerce_c_locale < 0) {
/* Signal handlers are installed by default */ config->coerce_c_locale = 0;
config->install_signal_handlers = 1; }
if (config->utf8_mode < 0) {
config->utf8_mode = 0;
} }
return _Py_INIT_OK(); return _Py_INIT_OK();
@ -2599,7 +2612,6 @@ pymain_init(_PyMain *pymain, PyInterpreterState **interp_p)
_PyCoreConfig local_config = _PyCoreConfig_INIT; _PyCoreConfig local_config = _PyCoreConfig_INIT;
_PyCoreConfig *config = &local_config; _PyCoreConfig *config = &local_config;
config->install_signal_handlers = 1;
_PyCoreConfig_GetGlobalConfig(config); _PyCoreConfig_GetGlobalConfig(config);