@@ -442,6 +442,7 @@ int pthread_attr_destroy(pthread_attr_t *a)
442
442
void
443
443
_Py_InitializeRecursionLimits (PyThreadState * tstate )
444
444
{
445
+ uintptr_t here_addr = _Py_get_machine_stack_pointer ();
445
446
_PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )tstate ;
446
447
#ifdef WIN32
447
448
ULONG_PTR low , high ;
@@ -458,8 +459,8 @@ _Py_InitializeRecursionLimits(PyThreadState *tstate)
458
459
_tstate -> c_stack_top = (uintptr_t )stack_addr ;
459
460
_tstate -> c_stack_hard_limit = _tstate -> c_stack_top - stack_size ;
460
461
_tstate -> c_stack_soft_limit = _tstate -> c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES ;
461
- #else
462
- uintptr_t here_addr = _Py_get_machine_stack_pointer () ;
462
+ #else // other platform
463
+ _tstate -> c_stack_top = 0 ;
463
464
/// XXX musl supports HAVE_PTHRED_GETATTR_NP, but the resulting stack size
464
465
/// (on alpine at least) is much smaller than expected and imposes undue limits
465
466
/// compared to the old stack size estimation. (We assume musl is not glibc.)
@@ -477,22 +478,31 @@ _Py_InitializeRecursionLimits(PyThreadState *tstate)
477
478
if (err == 0 ) {
478
479
uintptr_t base = ((uintptr_t )stack_addr ) + guard_size ;
479
480
_tstate -> c_stack_top = base + stack_size ;
480
- #ifdef _Py_THREAD_SANITIZER
481
+ # ifdef _Py_THREAD_SANITIZER
481
482
// Thread sanitizer crashes if we use a bit more than half the stack.
482
483
_tstate -> c_stack_soft_limit = base + (stack_size / 2 );
483
- #else
484
+ # else
484
485
_tstate -> c_stack_soft_limit = base + _PyOS_STACK_MARGIN_BYTES * 2 ;
485
- #endif
486
+ # endif
486
487
_tstate -> c_stack_hard_limit = base + _PyOS_STACK_MARGIN_BYTES ;
487
- assert (_tstate -> c_stack_soft_limit < here_addr );
488
- assert (here_addr < _tstate -> c_stack_top );
488
+ }
489
+ # endif // musl
490
+ #endif // platform-specific code
491
+
492
+ /* Check that we currently are inside the discovered stack.
493
+ * gh-139653: Boost's make_fcontext (and presumably other stack-switching
494
+ * mechanisms) may be incompatible with platform API.
495
+ */
496
+ if (_tstate -> c_stack_top
497
+ && _tstate -> c_stack_soft_limit < here_addr
498
+ && here_addr < _tstate -> c_stack_top
499
+ ) {
489
500
return ;
490
501
}
491
- # endif
502
+ // Generic fallback
492
503
_tstate -> c_stack_top = _Py_SIZE_ROUND_UP (here_addr , 4096 );
493
504
_tstate -> c_stack_soft_limit = _tstate -> c_stack_top - Py_C_STACK_SIZE ;
494
505
_tstate -> c_stack_hard_limit = _tstate -> c_stack_top - (Py_C_STACK_SIZE + _PyOS_STACK_MARGIN_BYTES );
495
- #endif
496
506
}
497
507
498
508
/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
0 commit comments