Skip to content

gh-127545: Specify minimum PyGC_Head and PyObject alignment to fix build failure #135016

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

fthain
Copy link

@fthain fthain commented Jun 2, 2025

As documented in InternalDocs/garbage_collector.md, the garbage collector stores flags in the least significant two bits of the _gc_prev pointer in struct PyGC_Head. Consequently, this pointer is only capable of storing a location that's aligned to a 4-byte boundary.

This alignment requirement is documented but it's not actually encoded. The code only works when python happens to run on a platform that has a sufficiently large minimum alignment for the structs in question.

The same problem arises with PyObject pointers because the least significant bits get used for PyStackRef tags.

Since we know that 2 bits are needed, we also know the minimum alignment that's needed. Let's make that explicit, so the compiler can then make those bits available.

This patch fixes a segfault in _bootstrap_python. In 3.14.0 beta 2 this fixes the error, "Assertion !PyStackRef_IsTaggedInt(ref)' failed" when building with --config-pydebug`.

Also, making the requirements explicit improves clarity.

This bug was previously investigated by Adrian Glaubitz here:
https://lists.debian.org/debian-68k/2024/11/msg00020.html
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087600

Although Adrian's patch isn't really correct (because natural alignment is not needed), he deserves full credit for finding the root cause.

Please see PR#127546 for the previous pull request.

As documented in InternalDocs/garbage_collector.md, the garbage collector
stores flags in the least significant two bits of the _gc_prev pointer
in struct PyGC_Head. Consequently, this pointer is only capable of storing
a location that's aligned to a 4-byte boundary.

This alignment requirement is documented but it's not actually encoded.
The code only works when python happens to run on a platform that has a
sufficiently large minimum alignment for the structs in question.

The same problem arises with PyObject pointers because the least
significant bits get used for PyStackRef tags.

Since we know that 2 bits are needed, we also know the minimum alignment
that's needed. Let's make that explicit, so the compiler can then make
those bits available.

This patch fixes a segfault in _bootstrap_python. In 3.14.0 beta 2
this fixes the "Assertion `!PyStackRef_IsTaggedInt(ref)' failed" when
built with --config-pydebug.

Also, making the requirements explicit improves clarity.

This bug was previously investigated by Adrian Glaubitz here:
https://lists.debian.org/debian-68k/2024/11/msg00020.html
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1087600

Although Adrian's patch isn't really correct (because natural alignment
is not needed), he deserves full credit for finding the root cause.
@fthain
Copy link
Author

fthain commented Jun 2, 2025

@ZeroIntensity, please go ahead and add labels when convenient.

@ZeroIntensity ZeroIntensity added needs backport to 3.13 bugs and security fixes OS-linux needs backport to 3.14 bugs and security fixes 🔨 test-with-buildbots Test PR w/ buildbots; report in status section labels Jun 2, 2025
@bedevere-bot
Copy link

🤖 New build scheduled with the buildbot fleet by @ZeroIntensity for commit 392f6c5 🤖

Results will be shown at:

https://buildbot.python.org/all/#/grid?branch=refs%2Fpull%2F135016%2Fmerge

If you want to schedule another build, you need to add the 🔨 test-with-buildbots label again.

@bedevere-bot bedevere-bot removed the 🔨 test-with-buildbots Test PR w/ buildbots; report in status section label Jun 2, 2025
@bedevere-app
Copy link

bedevere-app bot commented Jun 3, 2025

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@colesbury colesbury dismissed their stale review June 3, 2025 15:22

Ugh, I forgot that we are now using two bits in _PyStackRef...

I am still concerned about adding the the alignment attributes to Include/object.h.

@fthain
Copy link
Author

fthain commented Jun 4, 2025

@colesbury you mentioned that you still have concerns about the aligned attribute. Perhaps you can explain?

If your concern is that this change might be insufficient, because the codebase makes further unstated alignment assumptions, I think you may be right, since make test results seem to suggest this. However, if another flag bit is required in future, then the same problem will arise again and the same attribute will be needed for many more platforms.

uintptr_t _gc_prev;
} PyGC_Head;
} PyGC_Head Py_ALIGNED(1 << _PyObject_ALIGNMENT_SHIFT);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that Py_ALIGNED is only for GCC. I think we want the _Py_ALIGN_AS macro, but that seems to only be on the free-threaded build for some reason. See capi-workgroup/decisions#61.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants