Repository navigation
Fix object.__getstate__ deadlock and panic on __slotnames__ - #8981
luantaraschi wants to merge 1 commit into
Conversation
object_getstate_default kept the __slotnames__ list read-locked while it looked up each slot attribute. A getter or __getattr__ that changed the list (as in test_descr.test_issue24097) then waited forever for the write lock. A non-str entry in a cached __slotnames__ hit an unwrap and panicked. Take a reference to each name and drop the lock before the lookup, raise TypeError for a non-str name, let errors other than AttributeError propagate, and check the list size after each item, as CPython does. Assisted-by: Claude Code:claude-opus-5-5
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthrough
ChangesObject getstate slot handling
Priority: ⬇️ Low Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to No merge-blocking issue is identified; merge after normal checks. Security Architecture ReviewSecurity architecture risk: 🟡 Moderate · up to The change removes the reported deadlock and invalid-name panic paths, but introduces another possible native panic when a concurrent thread shrinks the slot-name list before an indexed read. This requires control of the list and concurrent execution; broader service impact or privilege escalation is not established. Retained concerns
Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📦 Library DependenciesThe following Lib/ modules were modified. Here are their dependencies: [x] test: cpython/Lib/test/test_descr.py (TODO: 2) dependencies: dependent tests: (no tests depend on descr) Legend:
|
Merging this PR will improve performance by 10.98%
Performance Changes
Tip Curious why performance improved? Comment Comparing Footnotes
|
|
@luantaraschi thank you for the patch! windows test hang looks like regression of this patch. could you take a look? |
Summary
object_getstate_defaultheld the__slotnames__read lock while it looked up each slot attribute. If a getter or__getattr__mutates the list during that lookup, which is exactly whattest_descr.test_issue24097does, it blocks on the write lock forever. On main that test hangs until the runner's 30 s timeout, so it was skipped.A non-str entry in a cached
__slotnames__hitdowncast_ref::<PyStr>().unwrap()instead:The loop now clones each name out of the list and drops the lock before the lookup, and raises
TypeError: attribute name must be string, not 'int'for a non-str name. OnlyAttributeErroris ignored now (throughget_attribute_opt): before, any exception from the lookup was swallowed, so a__getattr__raisingValueErrorgave a state ofNonewhere CPython raises. The size check runs after each item, as CPython does.Compared with CPython 3.14.7: the non-str and
ValueErrorcases now raise the same exception and message. The mutating case raisesRuntimeErrorlike CPython does, with our existing message (CPython spells it__slotsname__). A missing attribute is still skipped.test_issue24097intest_descr.pyis unskipped and passes. Fulltest_descr: OK.extra_tests/snippets/builtin_object.py.test_copy,test_copyreg,test_pickle,test_collections,test_dataclasses,test_enum,test_xml_etree,test_functools,test_dequeandtest_iopass as on main.cargo testfor the workspace (with the AGENTS.md exclusions),clippy -Dwarnings,cargo fmt --checkandcheck_redundant_patches.pyare clean. Linux only.Written with Claude Code (claude-opus-5-5) as a tool. I reviewed the diff and reproduced the hang and the panic before and after the change myself.
Summary by CodeRabbit
object.__getstate__handling of slot names: invalid entries and changes during lookup now raise clear errors, and errors reading slot values are no longer suppressed.