Fix some issues around TLS management with async (#2709)

This commit fixes a few issues around managing the thread-local state of
a wasmtime thread. We intentionally only have a singular TLS variable in
the whole world, and the problem is that when stack-switching off an
async thread we were not restoring the previous TLS state. This is
necessary in two cases:

* Futures aren't guaranteed to be polled/completed in a stack-like
  fashion. If a poll sees that a future isn't ready then we may resume
  execution in a previous wasm context that ends up needing the TLS
  information.

* Futures can also cross threads (when the whole store crosses threads)
  and we need to save/restore TLS state from the thread we're coming
  from and the thread that we're going to.

The stack switching issue necessitates some more glue around suspension
and resumption of a stack to ensure we save/restore the TLS state on
both sides. The thread issue, however, also necessitates that we use
`#[inline(never)]` on TLS access functions and never have TLS borrows
live across a function which could result in running arbitrary code (as
was the case for the `tls::set` function.
This commit is contained in:
Alex Crichton
2021-03-11 11:32:33 -06:00
committed by GitHub
parent 54c07d8f16
commit 918c012d00
4 changed files with 236 additions and 22 deletions

View File

@@ -717,7 +717,10 @@ impl Store {
Poll::Pending => {}
}
unsafe {
(*suspend).suspend(())?;
let before = wasmtime_runtime::TlsRestore::take();
let res = (*suspend).suspend(());
before.replace();
res?;
}
}
}