Skip to content

Commit

Permalink
Replace signals-based-traps with auto-detection (bytecodealliance#9941
Browse files Browse the repository at this point in the history
)

* Replace `signals-based-traps` with auto-detection

This commit refactors the platform support of the `wasmtime` crate
itself to remove the previously added `signals-based-traps` feature in
favor of auto-detecting whether it's there or not. The `build.rs`
script for the `wasmtime` crate will now detect the target platform and
auto-enable this feature as necessary.

The `signals-based-traps` cargo feature is removed and split into two
custom `#[cfg]` directives that the build script sets:

* `has_virtual_memory` - this is used to gate mmap implementations for
  example. This is enabled on `unix || windows` and will be off for
  `no_std` targets for example. This is split out of
  "signals-based-traps" to better handle platforms like iOS which have
  virtual memory but don't execute native code (removing the need for
  native signals).

* `has_native_signals` - gates signal handlers on Unix for example. This
  is disabled on MIRI but otherwise enabled for `unix || windows`. This
  is intended to in the future get disabled for iOS by default for
  example since it's not necessary when using Pulley. This is
  additionally off-by-default for `no_std` platforms.

Two new crate features were added for `no_std` or "custom" platforms to
opt-in to the `wasmtime-platform.h` C APIs for implementing virtual
memory and signals. These are used in the `min-platform` embedding example.

This commit additionally updates some various documentation here and
there to be more up-to-date.

* Update CI configuration

* Fix compile warnings

* Fix test on miri

* Fix more tests on miri

* Fix some warnings

* Another round of miri/CI attempts/fixes

prtest:full
  • Loading branch information
alexcrichton authored Jan 15, 2025
1 parent 73c4ff2 commit 7f9049b
Show file tree
Hide file tree
Showing 41 changed files with 290 additions and 291 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -371,8 +371,6 @@ jobs:
-p wasmtime --no-default-features --features threads
-p wasmtime --no-default-features --features runtime,threads
-p wasmtime --no-default-features --features cranelift,threads
-p wasmtime --no-default-features --features runtime,signals-based-traps
-p wasmtime --no-default-features --features runtime,gc,component-model,signals-based-traps
-p wasmtime --features incremental-cache
-p wasmtime --all-features
Expand Down Expand Up @@ -541,8 +539,6 @@ jobs:
test: >
cargo check -p wasmtime --no-default-features --features runtime,component-model &&
cargo check -p wasmtime --no-default-features --features runtime,gc,component-model &&
cargo check -p wasmtime --no-default-features --features runtime,gc,component-model,signals-based-traps &&
cargo check -p wasmtime --no-default-features --features runtime,gc,component-model,signals-based-traps &&
cargo check -p cranelift-control --no-default-features &&
cargo check -p pulley-interpreter --features encode,decode,disas,interp
# Use `cross` for illumos to have a C compiler/linker available.
Expand Down
4 changes: 1 addition & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ rustix = { workspace = true, features = ["mm", "param", "process"] }

[dev-dependencies]
# depend again on wasmtime to activate its default features for tests
wasmtime = { workspace = true, features = ['default', 'winch', 'pulley', 'all-arch', 'call-hook', 'memory-protection-keys', 'signals-based-traps'] }
wasmtime = { workspace = true, features = ['default', 'winch', 'pulley', 'all-arch', 'call-hook', 'memory-protection-keys'] }
env_logger = { workspace = true }
log = { workspace = true }
filecheck = { workspace = true }
Expand Down Expand Up @@ -416,7 +416,6 @@ default = [
"addr2line",
"debug-builtins",
"component-model",
"signals-based-traps",
"threads",
"gc",
"gc-drc",
Expand Down Expand Up @@ -475,7 +474,6 @@ threads = ["wasmtime-cli-flags/threads"]
gc = ["wasmtime-cli-flags/gc", "wasmtime/gc"]
gc-drc = ["gc", "wasmtime/gc-drc", "wasmtime-cli-flags/gc-drc"]
gc-null = ["gc", "wasmtime/gc-null", "wasmtime-cli-flags/gc-null"]
signals-based-traps = ["wasmtime/signals-based-traps", "wasmtime-cli-flags/signals-based-traps"]
pulley = ["wasmtime-cli-flags/pulley"]

# CLI subcommands for the `wasmtime` executable. See `wasmtime $cmd --help`
Expand Down
1 change: 0 additions & 1 deletion crates/cli-flags/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ gc-drc = ["gc", "wasmtime/gc-drc"]
gc-null = ["gc", "wasmtime/gc-null"]
threads = ["wasmtime/threads"]
memory-protection-keys = ["wasmtime/memory-protection-keys"]
signals-based-traps = ["wasmtime/signals-based-traps"]
pulley = ["wasmtime/pulley"]
48 changes: 16 additions & 32 deletions crates/cli-flags/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,47 +661,35 @@ impl CommonOptions {
.opts
.memory_reservation
.or(self.opts.static_memory_maximum_size);
match_feature! {
["signals-based-traps" : memory_reservation]
size => config.memory_reservation(size),
_ => err,
if let Some(size) = memory_reservation {
config.memory_reservation(size);
}

match_feature! {
["signals-based-traps" : self.opts.static_memory_forced]
enable => config.memory_may_move(!enable),
_ => err,
if let Some(enable) = self.opts.static_memory_forced {
config.memory_may_move(!enable);
}
match_feature! {
["signals-based-traps" : self.opts.memory_may_move]
enable => config.memory_may_move(enable),
_ => err,
if let Some(enable) = self.opts.memory_may_move {
config.memory_may_move(enable);
}

let memory_guard_size = self
.opts
.static_memory_guard_size
.or(self.opts.dynamic_memory_guard_size)
.or(self.opts.memory_guard_size);
match_feature! {
["signals-based-traps" : memory_guard_size]
size => config.memory_guard_size(size),
_ => err,
if let Some(size) = memory_guard_size {
config.memory_guard_size(size);
}

let mem_for_growth = self
.opts
.memory_reservation_for_growth
.or(self.opts.dynamic_memory_reserved_for_growth);
match_feature! {
["signals-based-traps" : mem_for_growth]
size => config.memory_reservation_for_growth(size),
_ => err,
if let Some(size) = mem_for_growth {
config.memory_reservation_for_growth(size);
}
match_feature! {
["signals-based-traps" : self.opts.guard_before_linear_memory]
enable => config.guard_before_linear_memory(enable),
_ => err,
if let Some(enable) = self.opts.guard_before_linear_memory {
config.guard_before_linear_memory(enable);
}
if let Some(enable) = self.opts.table_lazy_init {
config.table_lazy_init(enable);
Expand All @@ -718,15 +706,11 @@ impl CommonOptions {
if let Some(enable) = self.debug.address_map {
config.generate_address_map(enable);
}
match_feature! {
["signals-based-traps" : self.opts.memory_init_cow]
enable => config.memory_init_cow(enable),
_ => err,
if let Some(enable) = self.opts.memory_init_cow {
config.memory_init_cow(enable);
}
match_feature! {
["signals-based-traps" : self.opts.signals_based_traps]
enable => config.signals_based_traps(enable),
_ => err,
if let Some(enable) = self.opts.signals_based_traps {
config.signals_based_traps(enable);
}
if let Some(enable) = self.codegen.native_unwind_info {
config.native_unwind_info(enable);
Expand Down
2 changes: 1 addition & 1 deletion crates/fuzzing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ target-lexicon = { workspace = true }
tempfile = "3.3.0"
wasmparser = { workspace = true }
wasmprinter = { workspace = true }
wasmtime = { workspace = true, features = ['default', 'winch', 'gc', 'memory-protection-keys', 'signals-based-traps', 'pulley'] }
wasmtime = { workspace = true, features = ['default', 'winch', 'gc', 'memory-protection-keys', 'pulley'] }
wasmtime-wast = { workspace = true, features = ['component-model'] }
wasm-encoder = { workspace = true }
wasm-smith = { workspace = true }
Expand Down
5 changes: 3 additions & 2 deletions crates/test-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,10 @@ fn expand(test_config: &TestConfig, func: Fn) -> Result<TokenStream> {

for strategy in &test_config.strategies {
let strategy_name = format!("{strategy:?}");
// Winch currently only offers support for x64.
// Winch currently only offers support for x64, and it requires
// signals-based-traps which MIRI disables so disable winch tests on MIRI
let target = if *strategy == Compiler::Winch {
quote! { #[cfg(target_arch = "x86_64")] }
quote! { #[cfg(all(target_arch = "x86_64", not(miri)))] }
} else {
quote! {}
};
Expand Down
2 changes: 1 addition & 1 deletion crates/wasi-nn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ cap-std = { workspace = true }
libtest-mimic = { workspace = true }
test-programs-artifacts = { workspace = true }
wasmtime-wasi = { workspace = true, features = ["preview1"] }
wasmtime = { workspace = true, features = ["cranelift", 'signals-based-traps'] }
wasmtime = { workspace = true, features = ["cranelift"] }
tracing-subscriber = { workspace = true }

[features]
Expand Down
2 changes: 1 addition & 1 deletion crates/wasi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ test-log = { workspace = true }
tracing-subscriber = { workspace = true }
test-programs-artifacts = { workspace = true }
tempfile = { workspace = true }
wasmtime = { workspace = true, features = ['cranelift', 'incremental-cache', 'signals-based-traps'] }
wasmtime = { workspace = true, features = ['cranelift', 'incremental-cache'] }

[target.'cfg(unix)'.dependencies]
rustix = { workspace = true, features = ["event", "fs", "net"] }
Expand Down
35 changes: 14 additions & 21 deletions crates/wasmtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ default = [
'component-model',
'threads',
'std',
'signals-based-traps',
]

# An on-by-default feature enabling runtime compilation of WebAssembly modules
Expand Down Expand Up @@ -193,7 +192,6 @@ async = [
pooling-allocator = [
"runtime",
"std", # not ported to no_std yet
"signals-based-traps", # pooling allocation always uses mmap at this time
]

# Enables support for all architectures in Cranelift, allowing
Expand Down Expand Up @@ -250,6 +248,7 @@ runtime = [
"dep:rustix",
"rustix/mm",
"pulley-interpreter?/interp",
"dep:wasmtime-jit-icache-coherence",
]

# Enable support for garbage collection-related things.
Expand All @@ -273,7 +272,6 @@ gc = [
"wasmtime-environ/gc",
"wasmtime-cranelift?/gc",
"wasmtime-winch?/gc",
"signals-based-traps", # not ported to non-mmap schemes yet
]

# Enable the deferred reference counting garbage collector.
Expand All @@ -297,7 +295,6 @@ threads = [
"wasmtime-cranelift?/threads",
"wasmtime-winch?/threads",
"std",
"signals-based-traps",
]

# Controls whether backtraces will attempt to parse DWARF information in
Expand All @@ -319,13 +316,6 @@ std = [
'wasmtime-fiber?/std',
'pulley-interpreter?/std',
'wasmtime-math/std',
# technically this isn't necessary but once you have the standard library you
# probably want things to go fast in which case you've probably got signal
# handlers and such so implicitly enable this. This also helps reduce the
# verbosity of others depending on `wasmtime` with `default-features = false`
# where frequently `std` is enabled and this feature will typically want to be
# enabled by default as well.
'signals-based-traps',
]

# Enables support for the `Store::call_hook` API which enables injecting custom
Expand Down Expand Up @@ -357,14 +347,17 @@ reexport-wasmparser = []
# provides a human-readable text format for component values.
wave = ["dep:wasm-wave"]

# Gates compile-time support for host signals-based-traps.
# For platforms that Wasmtime does not have support for Wasmtime will disable
# the use of virtual memory by default, for example allocating linear memories
# with `malloc` instead. This feature can be used, for these platforms, to
# instead use a C API defined in `wasmtime-platform.h` instead.
#
# Traps based on signals, such as SIGSEGV, are useful for accelerating
# WebAssembly by removing explicit checks and letting the hardware deliver
# signals instead. This feature is enabled by default and gates a number
# of implementations within Wasmtime that may rely on virtual memory, for
# example. Embedded systems or smaller systems may wish to disable this feature
# to reduce the runtime requirements of Wasmtime.
signals-based-traps = [
"dep:wasmtime-jit-icache-coherence",
]
# For some more information see
# https://docs.wasmtime.dev/stability-platform-support.html#support-for-no_std
#
# This feature is not necessary for supported platforms like Unix and Windows as
# virtual memory is always enabled there.
custom-virtual-memory = []

# Same as `custom-virtual-memory` above, but for custom signal-handling APIs.
custom-native-signals = []
49 changes: 36 additions & 13 deletions crates/wasmtime/build.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,52 @@
fn main() {
println!("cargo:rerun-if-changed=build.rs");

// NB: duplicating a workaround in the wasmtime-fiber build script.
println!("cargo:rustc-check-cfg=cfg(asan)");
if cfg_is("sanitize", "address") {
println!("cargo:rustc-cfg=asan");
}

let unix = cfg("unix");
let windows = cfg("windows");
let miri = cfg("miri");
let supported_platform = unix || windows;

let has_native_signals =
!miri && (supported_platform || cfg!(feature = "custom-native-signals"));
let has_virtual_memory = supported_platform || cfg!(feature = "custom-virtual-memory");

println!("cargo:rustc-check-cfg=cfg(has_native_signals, has_virtual_memory)");
if has_native_signals {
println!("cargo:rustc-cfg=has_native_signals");
}
if has_virtual_memory {
println!("cargo:rustc-cfg=has_virtual_memory");
}

#[cfg(feature = "runtime")]
build_c_helpers();
}

fn cfg(key: &str) -> bool {
std::env::var(&format!("CARGO_CFG_{}", key.to_uppercase())).is_ok()
}

fn cfg_is(key: &str, val: &str) -> bool {
std::env::var(&format!("CARGO_CFG_{}", key.to_uppercase()))
.ok()
.as_deref()
== Some(val)
}

#[cfg(feature = "runtime")]
fn build_c_helpers() {
use wasmtime_versioned_export_macros::versioned_suffix;

// NB: duplicating a workaround in the wasmtime-fiber build script.
println!("cargo:rustc-check-cfg=cfg(asan)");
match std::env::var("CARGO_CFG_SANITIZE") {
Ok(s) if s == "address" => {
println!("cargo:rustc-cfg=asan");
}
_ => {}
}

// If this platform is neither unix nor windows then there's no default need
// for a C helper library since `helpers.c` is tailored for just these
// platforms currently.
if std::env::var("CARGO_CFG_UNIX").is_err() && std::env::var("CARGO_CFG_WINDOWS").is_err() {
if !cfg("unix") && !cfg("windows") {
return;
}

Expand All @@ -38,9 +63,7 @@ fn build_c_helpers() {

// On MinGW targets work around a bug in the MinGW compiler described at
// https://github.com/bytecodealliance/wasmtime/pull/9688#issuecomment-2573367719
if std::env::var("CARGO_CFG_WINDOWS").is_ok()
&& std::env::var("CARGO_CFG_TARGET_ENV").ok().as_deref() == Some("gnu")
{
if cfg("windows") && cfg_is("target_env", "gnu") {
build.define("__USE_MINGW_SETJMP_NON_SEH", None);
}

Expand Down
Loading

0 comments on commit 7f9049b

Please sign in to comment.