-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Alignment fault in PyMember_SetOne under freethreading on aarch64 #129675
Comments
It occurs to me that this problem may also be present but in a sense worse on x86. I believe on x86, the "atomic" access is silently not atomic if it's unaligned. Perhaps there's code to check this somewhere in the CPython implementation, though, otherwise this means ostensibly atomic accesses are actually racy. |
Can you provide some more information about how you end up with an offset and |
Here's a trivial repro, using nanobind: repro.cc:
r.py
CMakeLists.txt:
|
Thanks for the repro. I think this is a bug in nanobind, although the Python documentation and validation could be improved.
We can also add some additional validation of |
cc @encukou since this is related to PEP 697 |
See python/cpython#129675 (comment) tp_basicsize needs to be a multiple of the alignment of PyObject, which is in effect pointer aligned. This fixes a SIGBUS alignment crash found when testing free-threaded nanobind-using code on aarch64.
See python/cpython#129675 (comment) tp_basicsize needs to be a multiple of the alignment of PyObject, which is in effect pointer aligned. This fixes a SIGBUS alignment crash found when testing free-threaded nanobind-using code on aarch64.
This is now fixed in nanobind, but I think there's still a couple of action items here for CPython to document and enforce this. |
I think might be a bug in CPython. struct object44 {
PyObject header;
int array[7];
}; and the corresponding
For all major compilers, |
Not if pointers have 8 byte alignment (and if PyObject contains pointers). You need trailing padding so that the size of struct object44 arr[N]; Or allocate it using malloc: struct object44 *arr = malloc(sizeof(struct object44) * N); Every element must be satisfy the alignment of
Some compilers support |
See #129850 for the docs part. (If we add a warning, we shouldn't backport it, so it should be a separate PR.)
Huh, right, that's curious. I can't find it spelled out explicitly! |
I'd appreciate a review on the docs PR, especially from someone who knows* what I'll merge it next week if there are no objections. |
* Update documentation for tp_basicsize & tp_itemsize - Add alignment requirement - Mention that ob_size is unreliable if you don't control it - Add some links for context - basicsize should include the base type in generaly not just PyObject This adds a “by-the-way” link to `PyObject_New`, which shouldn't be used for GC types. In order to be comfortable linking to it, I also add a link to `PyObject_GC_New` from its docs. And the same for `*Var` variants, while I'm here. * Strongly suggest Py_SIZE & Py_SET_SIZE
…ythonGH-129850) * Update documentation for tp_basicsize & tp_itemsize - Add alignment requirement - Mention that ob_size is unreliable if you don't control it - Add some links for context - basicsize should include the base type in generaly not just PyObject This adds a “by-the-way” link to `PyObject_New`, which shouldn't be used for GC types. In order to be comfortable linking to it, I also add a link to `PyObject_GC_New` from its docs. And the same for `*Var` variants, while I'm here. * Strongly suggest Py_SIZE & Py_SET_SIZE (cherry picked from commit ad0f618) Co-authored-by: Petr Viktorin <encukou@gmail.com>
…ythonGH-129850) * Update documentation for tp_basicsize & tp_itemsize - Add alignment requirement - Mention that ob_size is unreliable if you don't control it - Add some links for context - basicsize should include the base type in generaly not just PyObject This adds a “by-the-way” link to `PyObject_New`, which shouldn't be used for GC types. In order to be comfortable linking to it, I also add a link to `PyObject_GC_New` from its docs. And the same for `*Var` variants, while I'm here. * Strongly suggest Py_SIZE & Py_SET_SIZE (cherry picked from commit ad0f618) Co-authored-by: Petr Viktorin <encukou@gmail.com>
…GH-129850) (GH-131078) - Add alignment requirement - Mention that ob_size is unreliable if you don't control it - Add some links for context - basicsize should include the base type in generaly not just PyObject - suggest Py_SIZE & Py_SET_SIZE This adds a “by-the-way” link to `PyObject_New`, which shouldn't be used for GC types. In order to be comfortable linking to it, I also add a link to `PyObject_GC_New` from its docs. And the same for `*Var` variants, while I'm here. (cherry picked from commit ad0f618) Co-authored-by: Petr Viktorin <encukou@gmail.com>
…GH-129850) (GH-131079) - Add alignment requirement - Mention that ob_size is unreliable if you don't control it - Add some links for context - basicsize should include the base type in generaly not just PyObject - suggest Py_SIZE & Py_SET_SIZE This adds a “by-the-way” link to `PyObject_New`, which shouldn't be used for GC types. In order to be comfortable linking to it, I also add a link to `PyObject_GC_New` from its docs. And the same for `*Var` variants, while I'm here. (cherry picked from commit ad0f618) Co-authored-by: Petr Viktorin <encukou@gmail.com>
Bug report
Bug description:
I saw a SIGBUS crash with the following backtrace immediately on startup when running a free-threaded build of https://github.com/jax-ml/jax on Python 3.13t:
What we're doing here is running this code:
and crashing.
We're at this line of code:
cpython/Python/structmember.c
Line 308 in 4f02615
Digging a little deeper, the relevant disassembly is:
What's going on here is that
stlr
's target address must be 8-byte aligned on aarch64: https://developer.arm.com/documentation/102336/0100/Load-Acquire-and-Store-Release-instructionsbut the
__doc__
field of this object is only 4-byte aligned, withoffset = 44
.We've placed an object field at an unaligned address, and used it in an atomic access that requires alignment, which is an error.
How should we fix this?
This seems like it's a CPython bug: CPython shouldn't choose underaligned slot offsets for object fields.
However, in this particular case it comes from a Python subclass of a C extension base class that has
tp_basicsize=44
; I'm also not aware of any rule that saystp_basicsize
has to be a multiple of the word size. Perhaps CPython should either enforce that or round up the size of base classes to ensure alignment.Or we can argue that CPython shouldn't be using an aligned atomic in this case.
What do you think?
CPython versions tested on:
3.13
Operating systems tested on:
Linux
Linked PRs
The text was updated successfully, but these errors were encountered: