| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
…til fully built frozendict.fromkeys() built its result with PyIter_Next() on an already GC-tracked object, so a half-built frozendict was reachable from another thread (using the gc module) and could be observed mutating mid-construction in the free threading build. Untrack the result while it is being filled and re-track it once fully built.
|
Let me take a closer look to see whether this is the right approach. Personally, I’m not a fan of calling _PyObject_GC_UNTRACK. I think it would be better for the object to start out untracked and transition to the tracked state once it is fully initialized. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
frozendict.fromkeys() fills its result by iterating the keys and inserting
them one at a time with PyIter_Next(), which runs user code (the iterable's
__next__). In the free-threaded build the result is GC-tracked during this
fill loop, so another thread calling gc.get_objects() can reach and take a
reference to the still half-built frozendict. That breaks the
unique-reference invariant the lock-free insert relies on, tripping
assert(can_modify_dict(mp)) on a debug build (or an unsynchronized write
concurrent with a reader on a release build).
This mirrors gh-151740, which applied the same untrack-during-build /
track-when-complete pattern to frozendict_new() and frozendict_vectorcall().
fromkeys() is the remaining construction path that change did not cover.
This is the separate follow-up for the fromkeys() path; in gh-151740
@corona10 suggested submitting it as its own PR once that one was merged.
Issue: #151722