228c52ed4a
TSAN instruments C++ code by adding prologue/epilogue code which maintains a shadow stack. Using setjmp()/longjmp() is intercepted by TSAN and correspondingly unwinds the shadow stack. When Dart VM throws exceptions we call the JumpToFrame stub from C++ which will directly reset the stack to the exception handler catch entry. This leaves the TSAN shadow stack unchanged. This means whenever an exception is thrown we leak frames in TSAN's shadow stack. Due to using a fixed-size shadow stack, it will cause a buffer-overflow in TSAN when too many such frame leaks happen. This can cause arbitrary memory to be overriden, leading to awkward crashes. This is especially an issue on the "iso-stres" builder because it launches - in the same process - *many* small tests, more easily hitting that limit. This CL will workaround the TSAN issue by making runtime call save it's state via setjmp() and make exception throughing process go via longjmp() (which TSAN will intercept) before actually calling the JumpToFrame stub. => This will ensure the TSAN shadow stack is correctly maintained. The [jmp_buf]'s encoding of register state is non-trivial (e.g. it uses XOR'ing of the actual saved state under certain glibc versions). So we store any state we need to pass to the target of the `longjmp()` on the [Thread] instead of overriding the [jmp_buf]s register state with the arguments. Issue https://github.com/dart-lang/sdk/issues/47472#issuecomment-948235479 TEST=vm/dart{,_2}/regress47472_test.dart Change-Id: Ifbf6580aa15bcce54d0584cdc3cd18cc19be0a9c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/222300 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Martin Kustermann <kustermann@google.com>