gh-149965: Improve thread-safety in ElementObjects within element_ass_subscr#149966
gh-149965: Improve thread-safety in ElementObjects within element_ass_subscr#149966clin1234 wants to merge 23 commits into
element_ass_subscr#149966Conversation
element_ass_subscr
|
|
||
| // Pointer-by-pointer memmove for PyObject** arrays that is safe | ||
| // for shared ElementObjects in Py_GIL_DISABLED builds. | ||
| static void |
There was a problem hiding this comment.
I'm not sure we should duplicate ptr_wise_atomic_memmove here.
Could you please link to the related C-API Working group issue in this PR, and cross-reference it in the original issue?
There was a problem hiding this comment.
Since the function is not exposed as part of the public API, I don't think linking a C-API Working Group issue is needed here.
Anyway, it's inspired by #149936
There was a problem hiding this comment.
I'll add a link to capi-workgroup/decisions#106 for traceability.
| // Pointer-by-pointer memmove for PyObject** arrays that is safe | ||
| // for shared ElementObjects in Py_GIL_DISABLED builds. | ||
| static void | ||
| ptr_wise_atomic_memmove(ElementObject *a, PyObject **dest, PyObject **src, Py_ssize_t n) |
There was a problem hiding this comment.
This function needs own set of unit tests, for:
- gil disabled
- single owner
- dest < src
- dest > str
- dest == src
- crazy, but someone will call it this way
- or an hard assertion forbidding such call
- or a short-circuit path if it's a no-on
- dest != src, but ranges overlap
…ternal helper and add unit tests Extract the duplicated static `ptr_wise_atomic_memmove` from `Modules/_elementtree.c` and `Objects/listobject.c` into a shared `static inline _Py_ptr_wise_atomic_memmove(PyObject *a, ...)` in `Include/internal/pycore_object.h`. The first parameter is generalised from a type-specific pointer to `PyObject *` since only `PyObject *`- level operations (`_Py_IsOwnedByCurrentThread`, `_PyObject_GC_IS_SHARED`) were ever performed on it. `listobject.c` previously embedded `_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED` inside the local helper. That assertion is preserved by moving it explicitly to each of the four call sites in `listobject.c` (which are all called under a critical section). `_elementtree.c`'s open question about whether a critical section is needed remains unanswered, so no assertion is added there. Unit tests are added in `Modules/_testinternalcapi/test_ptr_wise_memmove.c` covering: dest < src (forward copy), dest > src (backward copy), dest == src (no-op), overlapping ranges, and the single-owner fast path. The single-owner test explicitly clears the GC SHARED bit to guard against freelist reuse leaving the bit set from a sibling test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Commented out critical section assertion for ElementObject.
…FW3ZD.rst Co-authored-by: Sergey Miryanov <sergey.miryanov@gmail.com>
…ternal helper and add unit tests Extract the duplicated static `ptr_wise_atomic_memmove` from `Modules/_elementtree.c` and `Objects/listobject.c` into a shared `static inline _Py_ptr_wise_atomic_memmove(PyObject *a, ...)` in `Include/internal/pycore_object.h`. The first parameter is generalised from a type-specific pointer to `PyObject *` since only `PyObject *`- level operations (`_Py_IsOwnedByCurrentThread`, `_PyObject_GC_IS_SHARED`) were ever performed on it. `listobject.c` previously embedded `_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED` inside the local helper. That assertion is preserved by moving it explicitly to each of the four call sites in `listobject.c` (which are all called under a critical section). `_elementtree.c`'s open question about whether a critical section is needed remains unanswered, so no assertion is added there. Unit tests are added in `Modules/_testinternalcapi/test_ptr_wise_memmove.c` covering: dest < src (forward copy), dest > src (backward copy), dest == src (no-op), overlapping ranges, and the single-owner fast path. The single-owner test explicitly clears the GC SHARED bit to guard against freelist reuse leaving the bit set from a sibling test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ible on instances (pythonGH-139820) Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
|
@ericsnowcurrently, mind taking a look on helping me on resolving the mutable global variable issue in |
|
I tzhink the merge was messed up. There are unrelated changes. Please re-open a cleaner PR. |
…ternal helper and add unit tests Extract the duplicated static `ptr_wise_atomic_memmove` from `Modules/_elementtree.c` and `Objects/listobject.c` into a shared `static inline _Py_ptr_wise_atomic_memmove(PyObject *a, ...)` in `Include/internal/pycore_object.h`. The first parameter is generalised from a type-specific pointer to `PyObject *` since only `PyObject *`- level operations (`_Py_IsOwnedByCurrentThread`, `_PyObject_GC_IS_SHARED`) were ever performed on it. `listobject.c` previously embedded `_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED` inside the local helper. That assertion is preserved by moving it explicitly to each of the four call sites in `listobject.c` (which are all called under a critical section). `_elementtree.c`'s open question about whether a critical section is needed remains unanswered, so no assertion is added there. Unit tests are added in `Modules/_testinternalcapi/test_ptr_wise_memmove.c` covering: dest < src (forward copy), dest > src (backward copy), dest == src (no-op), overlapping ranges, and the single-owner fast path. The single-owner test explicitly clears the GC SHARED bit to guard against freelist reuse leaving the bit set from a sibling test. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
See also capi-workgroup/decisions#106