gh-157217: Fix dir() race when merging from a mappingproxy - #157279
Open
KingLizard1020 wants to merge 7 commits into
Open
gh-157217: Fix dir() race when merging from a mappingproxy#157279KingLizard1020 wants to merge 7 commits into
KingLizard1020 wants to merge 7 commits into
Conversation
KingLizard1020
requested review from
markshannon and
methane
as code owners
September 10, 2026 17:15
picnixz
reviewed
Sep 11, 2026
| * The struct layout matches mappingproxyobject in Objects/descrobject.c. | ||
| */ | ||
| static inline PyObject * | ||
| _PyDictProxy_GetMapping(PyObject *op) |
Member
There was a problem hiding this comment.
Why do you need it in the headers?
Author
There was a problem hiding this comment.
We don't — the helper was only used from dict_merge(). I dropped _PyDictProxy_GetMapping from the header and unwrapped the mapping locally there (Py_IS_TYPE, since mappingproxy is not a base type).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
dir(),dict(vars(cls)), and{**vars(cls)}go throughdict_merge()on a mappingproxy of the class dict. The generic merge path calledPyMapping_Keys()without holding the wrapped dict's critical section. On the free-threaded build, a concurrent insert (for example the first access to__annotations__, which stores__annotations_cache__) raisedRuntimeError: dictionary changed size during iteration.Unwrap
types.MappingProxyTypewhen it wraps a dict so the locked dict-to-dict path is used.Py_BEGIN_CRITICAL_SECTION2already treats a self-merge (a == source) as a single mutex.Tests:
Lib/test/test_dict_mappingproxy.pyfordict(),{**view}, andupdatefrom a mappingproxy (including aUserDictwrap, which still uses the generic path)test_dir_racing_class_dict_insertinLib/test/test_free_threading/test_type.py(free-threaded only). This failed with manyRuntimeErrors without the C change and passed with it.Fixes #157217
dir()can raiseRuntimeError: dictionary changed size during iterationon the free-threaded build #157217