Display stack trace at stack overflow (#32167)
authorJan Vorlicek <janvorli@microsoft.com>
Thu, 13 Feb 2020 00:05:52 +0000 (01:05 +0100)
committerGitHub <noreply@github.com>
Thu, 13 Feb 2020 00:05:52 +0000 (01:05 +0100)
commit134112a6ddfdf2a586e817f858fdd696f1c76e82
tree7a1a050c369d13173290bab08c449d51e14d0c91
parent1397c85ab6f0dbc64c2dbd2e5bdcbef736e66960
Display stack trace at stack overflow (#32167)

This is a fixed version of the reverted commit.

This change enables printing stack trace at stack overflow to the
console. In case multiple threads fail with stack overflow in parallel,
only the trace of the first thread is printed.

There are couple of interesting details:

The stack trace is printed in a compressed form. The algorithm finds the
largest sequence of frames starting from the top of the stack that is
repeated and prints it just once with the repeat count.
Only the first thread that hits stack overflow gets its stack printed.
On Linux, others threads that hit stack overflow are held spinning until
the process exits. This enables having a single preallocated stack for
handling stack overflow. On Windows, we just don't print the stack
trace, as it would be messy anyways due to the interleaving of output
from multiple threads and the value of getting stack overflow traces of
multiple threads is questionable.
On debug / checked builds for Windows, I had to bump the stack guarantee
by two pages and also enable setting the stack guarantee for all threads
in these build flavors.
At couple of places in the runtime, there were debug checks comparing
explicit frame and some other struct addresses to the current SP. These
were firing on Linux when we are running on an extra stack overflow
handling stack. I've fixed it by adding a flag to the Thread that
indicates that we are running on an alternate stack and these checks
should be skipped.
I've fixed the x86 Windows JIT_StackProbe to first probe at SP-4 and
then move the SP to leave more stack space for the handler.
I've fixed stack overflow check on Linux for some glibc / distros. The
stack limit returned by the pthread_attr_getstack returns the address of
the guard page in some of the glibc / distros and address of the last
accessible page before the guard page on others. So I've relaxed the
check to consider +/- 1 page around the stack limit to recognize sigsegv
as stack overflow.
28 files changed:
src/coreclr/src/debug/ee/controller.cpp
src/coreclr/src/inc/ex.h
src/coreclr/src/pal/src/arch/amd64/signalhandlerhelper.cpp
src/coreclr/src/pal/src/arch/arm/signalhandlerhelper.cpp
src/coreclr/src/pal/src/arch/arm64/signalhandlerhelper.cpp
src/coreclr/src/pal/src/arch/i386/signalhandlerhelper.cpp
src/coreclr/src/pal/src/exception/seh.cpp
src/coreclr/src/pal/src/exception/signal.cpp
src/coreclr/src/pal/src/include/pal/signal.hpp
src/coreclr/src/pal/src/thread/thread.cpp
src/coreclr/src/utilcode/ex.cpp
src/coreclr/src/vm/amd64/JitHelpers_Fast.asm
src/coreclr/src/vm/amd64/jithelpers_fast.S
src/coreclr/src/vm/arm/asmhelpers.S
src/coreclr/src/vm/arm/asmhelpers.asm
src/coreclr/src/vm/eedbginterface.h
src/coreclr/src/vm/eedbginterfaceimpl.cpp
src/coreclr/src/vm/eedbginterfaceimpl.h
src/coreclr/src/vm/eepolicy.cpp
src/coreclr/src/vm/excep.cpp
src/coreclr/src/vm/excep.h
src/coreclr/src/vm/exceptionhandling.cpp
src/coreclr/src/vm/frames.cpp
src/coreclr/src/vm/i386/jithelp.S
src/coreclr/src/vm/i386/jithelp.asm
src/coreclr/src/vm/stackwalk.cpp
src/coreclr/src/vm/threads.cpp
src/coreclr/src/vm/threads.h