Eryk Sun <[email protected]> added the comment:
In theory, a crash could be prevented in most cases by setting a larger stack
guarantee (i.e. region of guard pages) via SetThreadStackGuarantee() [1] and
using a vectored exception handler [2]. The exception handler can set a flag in
the thread state that indicates stack-overflow recovery is in progress and then
return EXCEPTION_CONTINUE_EXECUTION. The guaranteed stack space will be
available, but there are no guard pages, so another stack overflow in this
context will crash with an access violation. The stack guarantee should be
large enough to raise and unwind a RecursionError. As the stack unwinds, if the
recovery flag is still set, try calling _resetstkoflw() [3] to restore the
guard region. If it succeeds, clear the flag in the thread state.
For giggles, here's a toy example using ctypes:
import ctypes
import sys
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
ucrt = ctypes.CDLL('ucrtbase', use_errno=True)
EXCEPTION_CONTINUE_EXECUTION = 0xFFFFFFFF
stack_overflow = False
@ctypes.WINFUNCTYPE(ctypes.c_long, ctypes.c_void_p)
def handler(p):
global stack_overflow
stack_overflow = True
return EXCEPTION_CONTINUE_EXECUTION
kernel32.AddVectoredExceptionHandler(1, handler)
def recursive():
if stack_overflow:
raise RecursionError
recursive()
# Normally the stack has 2 or 3 guard pages, which is actually
# enough to recover in this example, but let's increase it to
# 9 pages (8 plus an extra that the memory manager adds). You
# can inspect this with Sysinternals VMMap.
size = ctypes.c_ulong(8 * 4096)
kernel32.SetThreadStackGuarantee(ctypes.byref(size))
sys.setrecursionlimit(1000000)
for n in range(5):
try:
recursive()
except RecursionError:
if stack_overflow and ucrt._resetstkoflw():
stack_overflow = False
print("recovered from stack overflow:", n)
---
[1]
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadstackguarantee
[2]
https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-addvectoredexceptionhandler
[3]
https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/resetstkoflw?view=msvc-160
----------
nosy: +eryksun
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue45645>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com