Skip to content

gh-151218: Replace sys.flags in PyConfig_Set()#151402

Merged
vstinner merged 10 commits into
python:mainfrom
vstinner:replace_sys_flags
Jun 16, 2026
Merged

gh-151218: Replace sys.flags in PyConfig_Set()#151402
vstinner merged 10 commits into
python:mainfrom
vstinner:replace_sys_flags

Conversation

@vstinner

@vstinner vstinner commented Jun 12, 2026

Copy link
Copy Markdown
Member

PyConfig_Set() and sys.set_int_max_str_digits() now replace sys.flags, instead of modifying sys.flags in-place.

Modifying sys.flags in-place can lead to data races when multiple threads are reading or writing sys.flags in parallel.

Use _Py_atomic functions to get and set max_str_digits members.

PyConfig_Set() and sys.set_int_max_str_digits() now replace
sys.flags, instead of modifying sys.flags in-place.

Modifying sys.flags in-place can lead to data races when multiple
threads are reading or writing sys.flags in parallel.

Use _Py_atomic functions to get and set max_str_digits members.
@vstinner

Copy link
Copy Markdown
Member Author

I built Python with ./configure --with-pydebug --disable-gil --with-thread-sanitizer CC=clang LD=clang and I ran the reproducer: TSan doesn't report data races anymore.

If we agree that this change is the right approach, I will add a non-regression test.

@skirpichev skirpichev self-requested a review June 12, 2026 13:44

@skirpichev skirpichev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a correct approach.

@vstinner

Copy link
Copy Markdown
Member Author

I added a thread test to test_free_threading.test_sys which is run by ./python -m test --tsan.

I also added some simple tests on get_int_max_str_digits() / set_int_max_str_digits() (in test_sys).

@vstinner

Copy link
Copy Markdown
Member Author

@picnixz @gpshead: Would you mind to review this fix?

@vstinner vstinner added needs backport to 3.15 pre-release feature fixes, bugs and security fixes needs backport to 3.14 bugs and security fixes labels Jun 15, 2026
@vstinner

Copy link
Copy Markdown
Member Author

Python 3.13 is not affected: sys.set_int_max_str_digits() only sets tstate->interp->long_state.max_str_digits, it doesn't update sys.flags. And PyConfig_Set() was only added to Python 3.14.

I modified sys.set_int_max_str_digits() in Python 3.14 when I implemented PEP 741 (PyConfig_Set()).

Comment thread Misc/NEWS.d/next/Core_and_Builtins/2026-06-12-15-30-25.gh-issue-151218.5M_nv8.rst Outdated
Comment thread Python/sysmodule.c Outdated
Comment thread Python/sysmodule.c
Comment thread Python/sysmodule.c
@read-the-docs-community

read-the-docs-community Bot commented Jun 16, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33163314 | 📁 Comparing 44bc1b2 against main (8646385)

  🔍 Preview build  

2 files changed
± c-api/init_config.html
± whatsnew/changelog.html

Comment thread Doc/c-api/init_config.rst
Comment thread Python/sysmodule.c Outdated
vstinner and others added 2 commits June 16, 2026 13:56
Update also outdated comment.
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
@vstinner

Copy link
Copy Markdown
Member Author

@picnixz: I addressed your review. Please review the updated PR.

@picnixz picnixz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Btw, I tried to delete sys.flags and it made the REPL "crash" (well just exit with an exception). I wonder whether sys.flags should be made non-deletable as well.

Comment thread Python/sysmodule.c Outdated
Comment thread Python/sysmodule.c
sys_set_flag(flags, pos, value);
Py_DECREF(flags);
return 0;
new_flags = PyStructSequence_New(&FlagsType);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this dance makes me wonder whether we need a PyStructSequence_Copy. Would be nicer to just copy the structure and alter one field.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I searched for PyStructSequence_New() and the only other place which creates a copy of an existing structseq is structseq_replace(): structseq.__replace__() method. I'm not sure that it's worth it to write a generic PyStructSequence_Copy() function.

Example using structseq.__replace__() method:

$ python
>>> import sys, copy
>>> copy.replace(sys.flags, verbose=3)
sys.flags(..., verbose=3, ...)

@vstinner

Copy link
Copy Markdown
Member Author

Btw, I tried to delete sys.flags and it made the REPL "crash" (well just exit with an exception). I wonder whether sys.flags should be made non-deletable as well.

In https://peps.python.org/pep-0726/ discussion, I mentioned that protecting sys attributes would be a good motivation to implement module __setattr__() and __delattr__(). Sadly, the SC decided to reject this PEP.

It's not easy to modify how module attributes are set and deleted in a C extension.

@vstinner vstinner enabled auto-merge (squash) June 16, 2026 16:03
@vstinner vstinner merged commit b16d23f into python:main Jun 16, 2026
54 checks passed
@vstinner vstinner deleted the replace_sys_flags branch June 16, 2026 16:17
@miss-islington-app

Copy link
Copy Markdown

Thanks @vstinner for the PR 🌮🎉.. I'm working now to backport this PR to: 3.14, 3.15.
🐍🍒⛏🤖

@miss-islington-app

Copy link
Copy Markdown

Sorry, @vstinner, I could not cleanly backport this to 3.14 due to a conflict.
Please backport using cherry_picker on command line.

cherry_picker b16d23fc9fe9cb72fa15c8a3036753e5437b5b8c 3.14

@bedevere-app

bedevere-app Bot commented Jun 16, 2026

Copy link
Copy Markdown

GH-151552 is a backport of this pull request to the 3.15 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.15 pre-release feature fixes, bugs and security fixes label Jun 16, 2026
@bedevere-app

bedevere-app Bot commented Jun 16, 2026

Copy link
Copy Markdown

GH-151553 is a backport of this pull request to the 3.14 branch.

@bedevere-app bedevere-app Bot removed the needs backport to 3.14 bugs and security fixes label Jun 16, 2026
vstinner added a commit that referenced this pull request Jun 16, 2026
…51552)

gh-151218: Replace sys.flags in PyConfig_Set() (GH-151402)

PyConfig_Set() and sys.set_int_max_str_digits() now replace
sys.flags (create a new object), instead of modifying sys.flags in-place.

Modifying sys.flags in-place can lead to data races when multiple
threads are reading or writing sys.flags in parallel.

Use _Py_atomic functions to get and set max_str_digits members.
(cherry picked from commit b16d23f)

Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
vstinner added a commit that referenced this pull request Jun 16, 2026
)

gh-151218: Replace sys.flags in PyConfig_Set() (#151402)

PyConfig_Set() and sys.set_int_max_str_digits() now replace
sys.flags (create a new object), instead of modifying sys.flags in-place.

Modifying sys.flags in-place can lead to data races when multiple
threads are reading or writing sys.flags in parallel.

Use _Py_atomic functions to get and set max_str_digits members.


(cherry picked from commit b16d23f)

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants