Skip to content

Commit a9dcf56

Browse files
committed
Specify minimum PyGC_Head alignment to fix build failure
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 works when python happens to run on a platform that has a large minimum alignment, but fails otherwise. 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 sure those 2 bits are available. This patch fixes a segfault in _bootstrap_python. It also clarifies the code by explicitly stating the actual requirement, in terms of _PyGC_PREV_SHIFT. 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.
1 parent b092705 commit a9dcf56

File tree

3 files changed

+5
-2
lines changed

3 files changed

+5
-2
lines changed

Include/internal/pycore_gc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ static inline void _PyObject_GC_SET_SHARED(PyObject *op) {
133133
*/
134134
#define _PyGC_NEXT_MASK_OLD_SPACE_1 1
135135

136-
#define _PyGC_PREV_SHIFT 2
137136
#define _PyGC_PREV_MASK (((uintptr_t) -1) << _PyGC_PREV_SHIFT)
138137

139138
/* set for debugging information */

Include/internal/pycore_interp_structs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ struct atexit_state {
155155

156156
/****** Garbage collector **********/
157157

158+
#define _PyGC_PREV_SHIFT 2
159+
158160
/* GC information is stored BEFORE the object structure. */
159161
typedef struct {
160162
// Tagged pointer to next object in the list.
@@ -163,8 +165,9 @@ typedef struct {
163165

164166
// Tagged pointer to previous object in the list.
165167
// Lowest two bits are used for flags documented later.
168+
// Those bits are made available by the struct's minimum alignment.
166169
uintptr_t _gc_prev;
167-
} PyGC_Head;
170+
} PyGC_Head Py_ALIGNED(1 << _PyGC_PREV_SHIFT);
168171

169172
#define _PyGC_Head_UNUSED PyGC_Head
170173

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix crash when building on Linux/m68k.

0 commit comments

Comments
 (0)