[wasm] Set thread-in-wasm flag correctly after stack unwinding

In Isolate::UnwindAndFindHandler(), the thread-in-wasm flag was set
before the destructor of some objects in that function got executed,
e.g. the destructor of {WasmCodeRefScope}. On Windows-asan, these
destructors could throw exceptions (asan on Windows uses exceptions for
its memory access tracking), which get handled initially by the wasm
trap handler, and would thereby invalidate the thread-in-wasm flag.

With this CL a new scope gets introduced which makes sure that setting
the thread-in-wasm flag is the last thing that happens in
Isolate::UnwindAndFindHandler().


Bug: chromium:1195595
Change-Id: If9f5f486c55b3bc2718a1d5aee3e3bd290d0ff35
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2817598
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73904}
This commit is contained in:
Andreas Haas 2021-04-12 09:26:15 +02:00 committed by Commit Bot
parent 02f84c745f
commit 15bf851978

View File

@ -1672,10 +1672,36 @@ Object Isolate::ReThrow(Object exception) {
return ReadOnlyRoots(heap()).exception();
}
namespace {
// This scope will set the thread-in-wasm flag after the execution of all
// destructors. The thread-in-wasm flag is only set when the scope gets enabled.
class SetThreadInWasmFlagScope {
public:
SetThreadInWasmFlagScope() {
DCHECK_IMPLIES(trap_handler::IsTrapHandlerEnabled(),
!trap_handler::IsThreadInWasm());
}
~SetThreadInWasmFlagScope() {
if (enabled_) trap_handler::SetThreadInWasm();
}
void Enable() { enabled_ = true; }
private:
bool enabled_ = false;
};
} // namespace
Object Isolate::UnwindAndFindHandler() {
// Create the {SetThreadInWasmFlagScope} first in this function so that its
// destructor gets called after all the other destructors. It is important
// that the destructor sets the thread-in-wasm flag after all other
// destructors. The other destructors may cause exceptions, e.g. ASan on
// Windows, which would invalidate the thread-in-wasm flag when the wasm trap
// handler handles such non-wasm exceptions.
SetThreadInWasmFlagScope set_thread_in_wasm_flag_scope;
Object exception = pending_exception();
DCHECK_IMPLIES(trap_handler::IsTrapHandlerEnabled(),
!trap_handler::IsThreadInWasm());
auto FoundHandler = [&](Context context, Address instruction_start,
intptr_t handler_offset,
@ -1768,9 +1794,10 @@ Object Isolate::UnwindAndFindHandler() {
StandardFrameConstants::kFixedFrameSizeAboveFp -
wasm_code->stack_slots() * kSystemPointerSize;
// This is going to be handled by Wasm, so we need to set the TLS flag.
trap_handler::SetThreadInWasm();
// This is going to be handled by WebAssembly, so we need to set the TLS
// flag. The {SetThreadInWasmFlagScope} will set the flag after all
// destructors have been executed.
set_thread_in_wasm_flag_scope.Enable();
return FoundHandler(Context(), wasm_code->instruction_start(), offset,
wasm_code->constant_pool(), return_sp, frame->fp());
}