Skip to content
Merged
Prev Previous commit
Next Next commit
Fix TSan: use larger minimum stack size
  • Loading branch information
vstinner committed Oct 7, 2025
commit b0d1cf38879ed3e1cf7bbda08f1a925eae012a9b
6 changes: 6 additions & 0 deletions Include/internal/pycore_pythonrun.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ extern const char* _Py_SourceAsString(
# define _PyOS_STACK_MARGIN_SHIFT (_PyOS_LOG2_STACK_MARGIN + 2)
#endif

#ifdef _Py_THREAD_SANITIZER
# define _PyOS_MIN_STACK_SIZE (_PyOS_STACK_MARGIN_BYTES * 6)
#else
# define _PyOS_MIN_STACK_SIZE (_PyOS_STACK_MARGIN_BYTES * 3)
#endif


#ifdef __cplusplus
}
Expand Down
6 changes: 3 additions & 3 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2425,9 +2425,8 @@ check_threadstate_set_stack(PyThreadState *tstate, void *start, size_t size)
assert(!PyErr_Occurred());

_PyThreadStateImpl *ts = (_PyThreadStateImpl *)tstate;
assert(ts->c_stack_hard_limit == (uintptr_t)start + _PyOS_STACK_MARGIN_BYTES);
assert(ts->c_stack_top == (uintptr_t)start + size);
assert(ts->c_stack_soft_limit >= ts->c_stack_hard_limit);
assert(ts->c_stack_hard_limit <= ts->c_stack_soft_limit);
assert(ts->c_stack_soft_limit < ts->c_stack_top);
}

Expand All @@ -2443,12 +2442,13 @@ test_threadstate_set_stack(PyObject *self, PyObject *Py_UNUSED(args))
size_t init_top = ts->c_stack_init_top;

// Test the minimum stack size
size_t size = _PyOS_STACK_MARGIN_BYTES * 3;
size_t size = _PyOS_MIN_STACK_SIZE;
void *start = (void*)(_Py_get_machine_stack_pointer() - size);
check_threadstate_set_stack(tstate, start, size);

// Test a larger size
size = 7654321;
assert(size > _PyOS_MIN_STACK_SIZE);
start = (void*)(_Py_get_machine_stack_pointer() - size);
check_threadstate_set_stack(tstate, start, size);

Expand Down
6 changes: 3 additions & 3 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,7 @@ tstate_set_stack(PyThreadState *tstate,
uintptr_t base, uintptr_t top)
{
assert(base < top);
assert((top - base) >= (_PyOS_STACK_MARGIN_BYTES * 3));
assert((top - base) >= _PyOS_MIN_STACK_SIZE);

#ifdef _Py_THREAD_SANITIZER
// Thread sanitizer crashes if we use more than half the stack.
Expand Down Expand Up @@ -533,10 +533,10 @@ int
PyUnstable_ThreadState_SetStack(PyThreadState *tstate,
void *stack_start_addr, size_t stack_size)
{
if (stack_size < (_PyOS_STACK_MARGIN_BYTES * 3)) {
if (stack_size < _PyOS_MIN_STACK_SIZE) {
PyErr_Format(PyExc_ValueError,
"stack_size must be at least %zu bytes",
_PyOS_STACK_MARGIN_BYTES * 3);
_PyOS_MIN_STACK_SIZE);
return -1;
}

Expand Down
Loading