Skip to content

Commit ecf411c

Browse files
authored
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.
1 parent 48ed88a commit ecf411c

5 files changed

Lines changed: 96 additions & 76 deletions

File tree

Include/pylifecycle.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,9 @@ PyAPI_FUNC(wchar_t *) Py_GetExecPrefix(void);
127127
PyAPI_FUNC(wchar_t *) Py_GetPath(void);
128128
#ifdef Py_BUILD_CORE
129129
struct _PyPathConfig;
130-
typedef struct _PyPathConfig _PyPathConfig;
131130

132131
PyAPI_FUNC(_PyInitError) _PyPathConfig_SetGlobal(
133-
const _PyPathConfig *config);
132+
const struct _PyPathConfig *config);
134133
PyAPI_FUNC(PyObject*) _PyPathConfig_ComputeArgv0(int argc, wchar_t **argv);
135134
PyAPI_FUNC(int) _Py_FindEnvConfigValue(
136135
FILE *env_file,

Include/pystate.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,23 @@ typedef PyObject* (*_PyFrameEvalFunction)(struct _frame *, int);
2626

2727

2828
typedef struct {
29-
int install_signal_handlers; /* Install signal handlers? -1 means unset */
29+
/* Install signal handlers? Yes by default. */
30+
int install_signal_handlers;
3031

3132
int ignore_environment; /* -E, Py_IgnoreEnvironmentFlag, -1 means unset */
3233
int use_hash_seed; /* PYTHONHASHSEED=x */
3334
unsigned long hash_seed;
34-
const char *allocator; /* Memory allocator: _PyMem_SetupAllocators() */
35+
const char *allocator; /* Memory allocator: PYTHONMALLOC */
3536
int dev_mode; /* PYTHONDEVMODE, -X dev */
36-
int faulthandler; /* PYTHONFAULTHANDLER, -X faulthandler */
37-
int tracemalloc; /* PYTHONTRACEMALLOC, -X tracemalloc=N */
37+
38+
/* Enable faulthandler?
39+
Set to 1 by -X faulthandler and PYTHONFAULTHANDLER. -1 means unset. */
40+
int faulthandler;
41+
42+
/* Enable tracemalloc?
43+
Set by -X tracemalloc=N and PYTHONTRACEMALLOC. -1 means unset */
44+
int tracemalloc;
45+
3846
int import_time; /* PYTHONPROFILEIMPORTTIME, -X importtime */
3947
int show_ref_count; /* -X showrefcount */
4048
int show_alloc_count; /* -X showalloccount */
@@ -229,9 +237,10 @@ typedef struct {
229237

230238
#define _PyCoreConfig_INIT \
231239
(_PyCoreConfig){ \
232-
.install_signal_handlers = -1, \
240+
.install_signal_handlers = 1, \
233241
.ignore_environment = -1, \
234242
.use_hash_seed = -1, \
243+
.faulthandler = -1, \
235244
.tracemalloc = -1, \
236245
.coerce_c_locale = -1, \
237246
.utf8_mode = -1, \

Lib/test/test_cmd_line.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -551,9 +551,7 @@ def run_xdev(self, *args, check_exitcode=True, xdev=True):
551551
env = dict(os.environ)
552552
env.pop('PYTHONWARNINGS', None)
553553
env.pop('PYTHONDEVMODE', None)
554-
# Force malloc() to disable the debug hooks which are enabled
555-
# by default for Python compiled in debug mode
556-
env['PYTHONMALLOC'] = 'malloc'
554+
env.pop('PYTHONMALLOC', None)
557555

558556
if xdev:
559557
args = (sys.executable, '-X', 'dev', *args)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-X dev: it is now possible to override the memory allocator using
2+
PYTHONMALLOC even if the developer mode is enabled.

Modules/main.c

Lines changed: 78 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
701701
config->LEN = config2->LEN; \
702702
} while (0)
703703

704+
COPY_ATTR(install_signal_handlers);
704705
COPY_ATTR(ignore_environment);
705706
COPY_ATTR(use_hash_seed);
706707
COPY_ATTR(hash_seed);
@@ -714,6 +715,9 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
714715
COPY_ATTR(show_alloc_count);
715716
COPY_ATTR(dump_refs);
716717
COPY_ATTR(malloc_stats);
718+
719+
COPY_ATTR(coerce_c_locale);
720+
COPY_ATTR(coerce_c_locale_warn);
717721
COPY_ATTR(utf8_mode);
718722

719723
COPY_STR_ATTR(pycache_prefix);
@@ -1244,9 +1248,7 @@ config_init_warnoptions(_PyCoreConfig *config, _PyCmdline *cmdline)
12441248
static _PyInitError
12451249
cmdline_init_env_warnoptions(_PyMain *pymain, _PyCoreConfig *config, _PyCmdline *cmdline)
12461250
{
1247-
if (config->ignore_environment) {
1248-
return _Py_INIT_OK();
1249-
}
1251+
assert(!config->ignore_environment);
12501252

12511253
wchar_t *env;
12521254
int res = config_get_env_var_dup(config, &env,
@@ -1819,37 +1821,6 @@ get_env_flag(_PyCoreConfig *config, int *flag, const char *name)
18191821
}
18201822

18211823

1822-
static void
1823-
cmdline_get_env_flags(_PyMain *pymain, _PyCoreConfig *config,
1824-
_PyCmdline *cmdline)
1825-
{
1826-
get_env_flag(config, &config->debug, "PYTHONDEBUG");
1827-
get_env_flag(config, &config->verbose, "PYTHONVERBOSE");
1828-
get_env_flag(config, &config->optimization_level, "PYTHONOPTIMIZE");
1829-
get_env_flag(config, &config->inspect, "PYTHONINSPECT");
1830-
1831-
int dont_write_bytecode = 0;
1832-
get_env_flag(config, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1833-
if (dont_write_bytecode) {
1834-
config->write_bytecode = 0;
1835-
}
1836-
1837-
int no_user_site_directory = 0;
1838-
get_env_flag(config, &no_user_site_directory, "PYTHONNOUSERSITE");
1839-
if (no_user_site_directory) {
1840-
config->user_site_directory = 0;
1841-
}
1842-
1843-
get_env_flag(config, &config->unbuffered_stdio, "PYTHONUNBUFFERED");
1844-
#ifdef MS_WINDOWS
1845-
get_env_flag(config, &config->legacy_windows_fs_encoding,
1846-
"PYTHONLEGACYWINDOWSFSENCODING");
1847-
get_env_flag(config, &config->legacy_windows_stdio,
1848-
"PYTHONLEGACYWINDOWSSTDIO");
1849-
#endif
1850-
}
1851-
1852-
18531824
static _PyInitError
18541825
config_init_home(_PyCoreConfig *config)
18551826
{
@@ -1944,7 +1915,37 @@ config_init_utf8_mode(_PyCoreConfig *config)
19441915
static _PyInitError
19451916
config_read_env_vars(_PyCoreConfig *config)
19461917
{
1947-
config->allocator = config_get_env_var(config, "PYTHONMALLOC");
1918+
assert(!config->ignore_environment);
1919+
1920+
/* Get environment variables */
1921+
get_env_flag(config, &config->debug, "PYTHONDEBUG");
1922+
get_env_flag(config, &config->verbose, "PYTHONVERBOSE");
1923+
get_env_flag(config, &config->optimization_level, "PYTHONOPTIMIZE");
1924+
get_env_flag(config, &config->inspect, "PYTHONINSPECT");
1925+
1926+
int dont_write_bytecode = 0;
1927+
get_env_flag(config, &dont_write_bytecode, "PYTHONDONTWRITEBYTECODE");
1928+
if (dont_write_bytecode) {
1929+
config->write_bytecode = 0;
1930+
}
1931+
1932+
int no_user_site_directory = 0;
1933+
get_env_flag(config, &no_user_site_directory, "PYTHONNOUSERSITE");
1934+
if (no_user_site_directory) {
1935+
config->user_site_directory = 0;
1936+
}
1937+
1938+
get_env_flag(config, &config->unbuffered_stdio, "PYTHONUNBUFFERED");
1939+
#ifdef MS_WINDOWS
1940+
get_env_flag(config, &config->legacy_windows_fs_encoding,
1941+
"PYTHONLEGACYWINDOWSFSENCODING");
1942+
get_env_flag(config, &config->legacy_windows_stdio,
1943+
"PYTHONLEGACYWINDOWSSTDIO");
1944+
#endif
1945+
1946+
if (config->allocator == NULL) {
1947+
config->allocator = config_get_env_var(config, "PYTHONMALLOC");
1948+
}
19481949

19491950
if (config_get_env_var(config, "PYTHONDUMPREFS")) {
19501951
config->dump_refs = 1;
@@ -1998,8 +1999,6 @@ config_read_complex_options(_PyCoreConfig *config)
19981999
config_get_env_var(config, "PYTHONDEVMODE"))
19992000
{
20002001
config->dev_mode = 1;
2001-
config->faulthandler = 1;
2002-
config->allocator = "debug";
20032002
}
20042003

20052004
_PyInitError err = pymain_init_tracemalloc(config);
@@ -2033,23 +2032,17 @@ pymain_read_conf_impl(_PyMain *pymain, _PyCoreConfig *config,
20332032
return res;
20342033
}
20352034

2036-
/* Get environment variables */
2037-
cmdline_get_env_flags(pymain, config, cmdline);
2038-
2039-
err = cmdline_init_env_warnoptions(pymain, config, cmdline);
2040-
if (_Py_INIT_FAILED(err)) {
2041-
pymain->err = err;
2035+
if (pymain_init_core_argv(pymain, config, cmdline) < 0) {
20422036
return -1;
20432037
}
20442038

2045-
#ifdef MS_WINDOWS
2046-
if (config->legacy_windows_fs_encoding) {
2047-
config->utf8_mode = 0;
2048-
}
2049-
#endif
2050-
2051-
if (pymain_init_core_argv(pymain, config, cmdline) < 0) {
2052-
return -1;
2039+
assert(config->ignore_environment >= 0);
2040+
if (!config->ignore_environment) {
2041+
err = cmdline_init_env_warnoptions(pymain, config, cmdline);
2042+
if (_Py_INIT_FAILED(err)) {
2043+
pymain->err = err;
2044+
return -1;
2045+
}
20532046
}
20542047

20552048
err = _PyCoreConfig_Read(config);
@@ -2186,14 +2179,6 @@ config_init_locale(_PyCoreConfig *config)
21862179
}
21872180
return;
21882181
}
2189-
2190-
/* By default, C locale coercion and UTF-8 Mode are disabled */
2191-
if (config->coerce_c_locale < 0) {
2192-
config->coerce_c_locale = 0;
2193-
}
2194-
if (config->utf8_mode < 0) {
2195-
config->utf8_mode = 0;
2196-
}
21972182
}
21982183

21992184

@@ -2216,9 +2201,12 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
22162201

22172202
_PyCoreConfig_GetGlobalConfig(config);
22182203

2219-
err = config_read_env_vars(config);
2220-
if (_Py_INIT_FAILED(err)) {
2221-
return err;
2204+
assert(config->ignore_environment >= 0);
2205+
if (!config->ignore_environment) {
2206+
err = config_read_env_vars(config);
2207+
if (_Py_INIT_FAILED(err)) {
2208+
return err;
2209+
}
22222210
}
22232211

22242212
/* -X options */
@@ -2260,13 +2248,38 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
22602248
}
22612249
}
22622250

2251+
/* options side effects */
2252+
if (config->dev_mode) {
2253+
if (config->faulthandler < 0) {
2254+
config->faulthandler = 1;
2255+
}
2256+
if (config->allocator == NULL) {
2257+
config->allocator = "debug";
2258+
}
2259+
}
2260+
2261+
#ifdef MS_WINDOWS
2262+
if (config->legacy_windows_fs_encoding) {
2263+
config->utf8_mode = 0;
2264+
}
2265+
#endif
2266+
22632267
/* default values */
2268+
if (config->use_hash_seed < 0) {
2269+
config->use_hash_seed = 0;
2270+
config->hash_seed = 0;
2271+
}
2272+
if (config->faulthandler < 0) {
2273+
config->faulthandler = 0;
2274+
}
22642275
if (config->tracemalloc < 0) {
22652276
config->tracemalloc = 0;
22662277
}
2267-
if (config->install_signal_handlers < 0) {
2268-
/* Signal handlers are installed by default */
2269-
config->install_signal_handlers = 1;
2278+
if (config->coerce_c_locale < 0) {
2279+
config->coerce_c_locale = 0;
2280+
}
2281+
if (config->utf8_mode < 0) {
2282+
config->utf8_mode = 0;
22702283
}
22712284

22722285
return _Py_INIT_OK();
@@ -2599,7 +2612,6 @@ pymain_init(_PyMain *pymain, PyInterpreterState **interp_p)
25992612

26002613
_PyCoreConfig local_config = _PyCoreConfig_INIT;
26012614
_PyCoreConfig *config = &local_config;
2602-
config->install_signal_handlers = 1;
26032615

26042616
_PyCoreConfig_GetGlobalConfig(config);
26052617

0 commit comments

Comments
 (0)