Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit af1d64d

Browse filesBrowse files
authored
bpo-42260: Main init modify sys.flags in-place (GH-23150)
When Py_Initialize() is called twice, the second call now updates more sys attributes for the configuration, rather than only sys.argv. * Rename _PySys_InitMain() to _PySys_UpdateConfig(). * _PySys_UpdateConfig() now modifies sys.flags in-place, instead of creating a new flags object. * Remove old commented sys.flags flags (unbuffered and skip_first). * Add private _PySys_GetObject() function. * When Py_Initialize(), Py_InitializeFromConfig() and
1 parent 58ca33b commit af1d64d
Copy full SHA for af1d64d

File tree

4 files changed

+89
-74
lines changed
Filter options

4 files changed

+89
-74
lines changed

‎Include/internal/pycore_pylifecycle.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_pylifecycle.h
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ extern PyStatus _PySys_Create(
4444
PyObject **sysmod_p);
4545
extern PyStatus _PySys_ReadPreinitWarnOptions(PyWideStringList *options);
4646
extern PyStatus _PySys_ReadPreinitXOptions(PyConfig *config);
47-
extern int _PySys_InitMain(PyThreadState *tstate);
47+
extern int _PySys_UpdateConfig(PyThreadState *tstate);
4848
extern PyStatus _PyExc_Init(PyThreadState *tstate);
4949
extern PyStatus _PyErr_Init(void);
5050
extern PyStatus _PyBuiltins_AddExceptions(PyObject * bltinmod);
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
When :c:func:`Py_Initialize` is called twice, the second call now updates
2+
more :mod:`sys` attributes for the configuration, rather than only
3+
:data:`sys.argv`. Patch by Victor Stinner.

‎Python/pylifecycle.c

Copy file name to clipboardExpand all lines: Python/pylifecycle.c
+18-27Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -949,19 +949,10 @@ pyinit_core(_PyRuntimeState *runtime,
949949
configuration. Example of bpo-34008: Py_Main() called after
950950
Py_Initialize(). */
951951
static PyStatus
952-
_Py_ReconfigureMainInterpreter(PyThreadState *tstate)
952+
pyinit_main_reconfigure(PyThreadState *tstate)
953953
{
954-
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
955-
956-
PyObject *argv = _PyWideStringList_AsList(&config->argv);
957-
if (argv == NULL) {
958-
return _PyStatus_NO_MEMORY(); \
959-
}
960-
961-
int res = PyDict_SetItemString(tstate->interp->sysdict, "argv", argv);
962-
Py_DECREF(argv);
963-
if (res < 0) {
964-
return _PyStatus_ERR("fail to set sys.argv");
954+
if (_PySys_UpdateConfig(tstate) < 0) {
955+
return _PyStatus_ERR("fail to update sys for the new conf");
965956
}
966957
return _PyStatus_OK();
967958
}
@@ -995,7 +986,7 @@ init_interp_main(PyThreadState *tstate)
995986
}
996987
}
997988

998-
if (_PySys_InitMain(tstate) < 0) {
989+
if (_PySys_UpdateConfig(tstate) < 0) {
999990
return _PyStatus_ERR("can't finish initializing sys");
1000991
}
1001992

@@ -1100,7 +1091,7 @@ pyinit_main(PyThreadState *tstate)
11001091
}
11011092

11021093
if (interp->runtime->initialized) {
1103-
return _Py_ReconfigureMainInterpreter(tstate);
1094+
return pyinit_main_reconfigure(tstate);
11041095
}
11051096

11061097
PyStatus status = init_interp_main(tstate);
@@ -1111,19 +1102,6 @@ pyinit_main(PyThreadState *tstate)
11111102
}
11121103

11131104

1114-
PyStatus
1115-
_Py_InitializeMain(void)
1116-
{
1117-
PyStatus status = _PyRuntime_Initialize();
1118-
if (_PyStatus_EXCEPTION(status)) {
1119-
return status;
1120-
}
1121-
_PyRuntimeState *runtime = &_PyRuntime;
1122-
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
1123-
return pyinit_main(tstate);
1124-
}
1125-
1126-
11271105
PyStatus
11281106
Py_InitializeFromConfig(const PyConfig *config)
11291107
{
@@ -1191,6 +1169,19 @@ Py_Initialize(void)
11911169
}
11921170

11931171

1172+
PyStatus
1173+
_Py_InitializeMain(void)
1174+
{
1175+
PyStatus status = _PyRuntime_Initialize();
1176+
if (_PyStatus_EXCEPTION(status)) {
1177+
return status;
1178+
}
1179+
_PyRuntimeState *runtime = &_PyRuntime;
1180+
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
1181+
return pyinit_main(tstate);
1182+
}
1183+
1184+
11941185
static void
11951186
finalize_modules_delete_special(PyThreadState *tstate, int verbose)
11961187
{

‎Python/sysmodule.c

Copy file name to clipboardExpand all lines: Python/sysmodule.c
+67-46Lines changed: 67 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,24 @@ _PySys_GetObjectId(_Py_Identifier *key)
8484
return sys_get_object_id(tstate, key);
8585
}
8686

87+
static PyObject *
88+
_PySys_GetObject(PyThreadState *tstate, const char *name)
89+
{
90+
PyObject *sysdict = tstate->interp->sysdict;
91+
if (sysdict == NULL) {
92+
return NULL;
93+
}
94+
return _PyDict_GetItemStringWithError(sysdict, name);
95+
}
96+
8797
PyObject *
8898
PySys_GetObject(const char *name)
8999
{
90100
PyThreadState *tstate = _PyThreadState_GET();
91-
PyObject *sd = tstate->interp->sysdict;
92-
if (sd == NULL) {
93-
return NULL;
94-
}
101+
95102
PyObject *exc_type, *exc_value, *exc_tb;
96103
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
97-
PyObject *value = _PyDict_GetItemStringWithError(sd, name);
104+
PyObject *value = _PySys_GetObject(tstate, name);
98105
/* XXX Suppress a new exception if it was raised and restore
99106
* the old one. */
100107
_PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
@@ -2464,8 +2471,6 @@ static PyStructSequence_Field flags_fields[] = {
24642471
{"no_site", "-S"},
24652472
{"ignore_environment", "-E"},
24662473
{"verbose", "-v"},
2467-
/* {"unbuffered", "-u"}, */
2468-
/* {"skip_first", "-x"}, */
24692474
{"bytes_warning", "-b"},
24702475
{"quiet", "-q"},
24712476
{"hash_randomization", "-R"},
@@ -2482,21 +2487,27 @@ static PyStructSequence_Desc flags_desc = {
24822487
15
24832488
};
24842489

2485-
static PyObject*
2486-
make_flags(PyThreadState *tstate)
2490+
static int
2491+
set_flags_from_config(PyObject *flags, PyThreadState *tstate)
24872492
{
24882493
PyInterpreterState *interp = tstate->interp;
24892494
const PyPreConfig *preconfig = &interp->runtime->preconfig;
24902495
const PyConfig *config = _PyInterpreterState_GetConfig(interp);
24912496

2492-
PyObject *seq = PyStructSequence_New(&FlagsType);
2493-
if (seq == NULL) {
2494-
return NULL;
2495-
}
2496-
2497-
int pos = 0;
2498-
#define SetFlag(flag) \
2499-
PyStructSequence_SET_ITEM(seq, pos++, PyLong_FromLong(flag))
2497+
// _PySys_UpdateConfig() modifies sys.flags in-place:
2498+
// Py_XDECREF() is needed in this case.
2499+
Py_ssize_t pos = 0;
2500+
#define SetFlagObj(expr) \
2501+
do { \
2502+
PyObject *value = (expr); \
2503+
if (value == NULL) { \
2504+
return -1; \
2505+
} \
2506+
Py_XDECREF(PyStructSequence_GET_ITEM(flags, pos)); \
2507+
PyStructSequence_SET_ITEM(flags, pos, value); \
2508+
pos++; \
2509+
} while (0)
2510+
#define SetFlag(expr) SetFlagObj(PyLong_FromLong(expr))
25002511

25012512
SetFlag(config->parser_debug);
25022513
SetFlag(config->inspect);
@@ -2507,23 +2518,34 @@ make_flags(PyThreadState *tstate)
25072518
SetFlag(!config->site_import);
25082519
SetFlag(!config->use_environment);
25092520
SetFlag(config->verbose);
2510-
/* SetFlag(saw_unbuffered_flag); */
2511-
/* SetFlag(skipfirstline); */
25122521
SetFlag(config->bytes_warning);
25132522
SetFlag(config->quiet);
25142523
SetFlag(config->use_hash_seed == 0 || config->hash_seed != 0);
25152524
SetFlag(config->isolated);
2516-
PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(config->dev_mode));
2525+
SetFlagObj(PyBool_FromLong(config->dev_mode));
25172526
SetFlag(preconfig->utf8_mode);
2527+
#undef SetFlagObj
25182528
#undef SetFlag
2529+
return 0;
2530+
}
25192531

2520-
if (_PyErr_Occurred(tstate)) {
2521-
Py_DECREF(seq);
2532+
2533+
static PyObject*
2534+
make_flags(PyThreadState *tstate)
2535+
{
2536+
PyObject *flags = PyStructSequence_New(&FlagsType);
2537+
if (flags == NULL) {
25222538
return NULL;
25232539
}
2524-
return seq;
2540+
2541+
if (set_flags_from_config(flags, tstate) < 0) {
2542+
Py_DECREF(flags);
2543+
return NULL;
2544+
}
2545+
return flags;
25252546
}
25262547

2548+
25272549
PyDoc_STRVAR(version_info__doc__,
25282550
"sys.version_info\n\
25292551
\n\
@@ -2767,14 +2789,23 @@ _PySys_InitCore(PyThreadState *tstate, PyObject *sysdict)
27672789
/* implementation */
27682790
SET_SYS("implementation", make_impl_info(version_info));
27692791

2770-
/* flags */
2792+
// sys.flags: updated in-place later by _PySys_UpdateConfig()
27712793
if (FlagsType.tp_name == 0) {
27722794
if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0) {
27732795
goto type_init_failed;
27742796
}
27752797
}
2776-
/* Set flags to their default values (updated by _PySys_InitMain()) */
27772798
SET_SYS("flags", make_flags(tstate));
2799+
/* prevent user from creating new instances */
2800+
FlagsType.tp_init = NULL;
2801+
FlagsType.tp_new = NULL;
2802+
res = PyDict_DelItemString(FlagsType.tp_dict, "__new__");
2803+
if (res < 0) {
2804+
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
2805+
goto err_occurred;
2806+
}
2807+
_PyErr_Clear(tstate);
2808+
}
27782809

27792810
#if defined(MS_WINDOWS)
27802811
/* getwindowsversion */
@@ -2876,8 +2907,10 @@ sys_create_xoptions_dict(const PyConfig *config)
28762907
}
28772908

28782909

2910+
// Update sys attributes for a new PyConfig configuration.
2911+
// This function also adds attributes that _PySys_InitCore() didn't add.
28792912
int
2880-
_PySys_InitMain(PyThreadState *tstate)
2913+
_PySys_UpdateConfig(PyThreadState *tstate)
28812914
{
28822915
PyObject *sysdict = tstate->interp->sysdict;
28832916
const PyConfig *config = _PyInterpreterState_GetConfig(tstate->interp);
@@ -2914,28 +2947,16 @@ _PySys_InitMain(PyThreadState *tstate)
29142947
#undef COPY_LIST
29152948
#undef SET_SYS_FROM_WSTR
29162949

2917-
2918-
/* Set flags to their final values */
2919-
SET_SYS("flags", make_flags(tstate));
2920-
/* prevent user from creating new instances */
2921-
FlagsType.tp_init = NULL;
2922-
FlagsType.tp_new = NULL;
2923-
res = PyDict_DelItemString(FlagsType.tp_dict, "__new__");
2924-
if (res < 0) {
2925-
if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
2926-
return res;
2927-
}
2928-
_PyErr_Clear(tstate);
2950+
// sys.flags
2951+
PyObject *flags = _PySys_GetObject(tstate, "flags"); // borrowed ref
2952+
if (flags == NULL) {
2953+
return -1;
29292954
}
2930-
2931-
SET_SYS("dont_write_bytecode", PyBool_FromLong(!config->write_bytecode));
2932-
2933-
if (get_warnoptions(tstate) == NULL) {
2955+
if (set_flags_from_config(flags, tstate) < 0) {
29342956
return -1;
29352957
}
29362958

2937-
if (get_xoptions(tstate) == NULL)
2938-
return -1;
2959+
SET_SYS("dont_write_bytecode", PyBool_FromLong(!config->write_bytecode));
29392960

29402961
if (_PyErr_Occurred(tstate)) {
29412962
goto err_occurred;
@@ -2977,8 +2998,8 @@ _PySys_SetPreliminaryStderr(PyObject *sysdict)
29772998
}
29782999

29793000

2980-
/* Create sys module without all attributes: _PySys_InitMain() should be called
2981-
later to add remaining attributes. */
3001+
/* Create sys module without all attributes.
3002+
_PySys_UpdateConfig() should be called later to add remaining attributes. */
29823003
PyStatus
29833004
_PySys_Create(PyThreadState *tstate, PyObject **sysmod_p)
29843005
{

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.