* and should be placed at the beginning. */
struct _ceval_state ceval;
- /* This structure is carefully allocated so that it's correctly aligned
- * to avoid undefined behaviors during LOAD and STORE. The '_malloced'
- * field stores the allocated pointer address that will later be freed.
- */
+ // unused, kept for ABI compatibility
void *_malloced;
PyInterpreterState *next;
self.assertEqual(os.read(r_interp, 1), DONE)
@cpython_only
+ @support.skip_if_sanitizer(thread=True, memory=True)
def test_daemon_threads_fatal_error(self):
import_module("_testcapi")
subinterp_code = f"""if 1:
static PyInterpreterState *
alloc_interpreter(void)
{
+ // Aligned allocation for PyInterpreterState.
+ // the first word of the memory block is used to store
+ // the original pointer to be used later to free the memory.
size_t alignment = _Alignof(PyInterpreterState);
- size_t allocsize = sizeof(PyInterpreterState) + alignment - 1;
+ size_t allocsize = sizeof(PyInterpreterState) + sizeof(void *) + alignment - 1;
void *mem = PyMem_RawCalloc(1, allocsize);
if (mem == NULL) {
return NULL;
}
- PyInterpreterState *interp = _Py_ALIGN_UP(mem, alignment);
- assert(_Py_IS_ALIGNED(interp, alignment));
- interp->_malloced = mem;
- return interp;
+ void *ptr = _Py_ALIGN_UP((char *)mem + sizeof(void *), alignment);
+ ((void **)ptr)[-1] = mem;
+ assert(_Py_IS_ALIGNED(ptr, alignment));
+ return ptr;
}
static void
interp->obmalloc = NULL;
}
assert(_Py_IS_ALIGNED(interp, _Alignof(PyInterpreterState)));
- PyMem_RawFree(interp->_malloced);
+ PyMem_RawFree(((void **)interp)[-1]);
}
}