MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / call_async

Function call_async

crates/fuzzing/src/oracles.rs:1077–1248  ·  view source on GitHub ↗

Instantiates a wasm module and runs its exports with dummy values, all in an async fashion. Attempts to stress yields in host functions to ensure that exiting and resuming a wasm function call works.

(wasm: &[u8], config: &generators::Config, mut poll_amts: &[u32])

Source from the content-addressed store, hash-verified

1075/// Attempts to stress yields in host functions to ensure that exiting and
1076/// resuming a wasm function call works.
1077pub fn call_async(wasm: &[u8], config: &generators::Config, mut poll_amts: &[u32]) {
1078 let mut store = config.to_store();
1079 let module = match compile_module(store.engine(), wasm, KnownValid::Yes, config) {
1080 Some(module) => module,
1081 None => return,
1082 };
1083
1084 // Configure a helper thread to periodically increment the epoch to
1085 // forcibly enable yields-via-epochs if epochs are in use. Note that this
1086 // is required because the wasm isn't otherwise guaranteed to necessarily
1087 // call any imports which will also increment the epoch.
1088 let mut helper_thread = HelperThread::default();
1089 if let generators::AsyncConfig::YieldWithEpochs { dur, .. } = &config.wasmtime.async_config {
1090 let engine = store.engine().clone();
1091 helper_thread.run_periodically(*dur, move || engine.increment_epoch());
1092 }
1093
1094 // Generate a `Linker` where all function imports are custom-built to yield
1095 // periodically and additionally increment the epoch.
1096 let mut imports = Vec::new();
1097 for import in module.imports() {
1098 let item = match import.ty() {
1099 ExternType::Func(ty) => {
1100 let poll_amt = take_poll_amt(&mut poll_amts);
1101 Func::new_async(&mut store, ty.clone(), move |caller, _, results| {
1102 let ty = ty.clone();
1103 Box::new(async move {
1104 caller.engine().increment_epoch();
1105 log::info!("yielding {poll_amt} times in import");
1106 YieldN(poll_amt).await;
1107 for (ret_ty, result) in ty.results().zip(results) {
1108 *result = ret_ty.default_value().unwrap();
1109 }
1110 Ok(())
1111 })
1112 })
1113 .into()
1114 }
1115 other_ty => match other_ty.default_value(&mut store) {
1116 Ok(item) => item,
1117 Err(e) => {
1118 log::warn!("couldn't create import for {import:?}: {e:?}");
1119 return;
1120 }
1121 },
1122 };
1123 imports.push(item);
1124 }
1125
1126 // Run the instantiation process, asynchronously, and if everything
1127 // succeeds then pull out the instance.
1128 // log::info!("starting instantiation");
1129 let instance = block_on(Timeout {
1130 future: Instance::new_async(&mut store, &module, &imports),
1131 polls: take_poll_amt(&mut poll_amts),
1132 end: Instant::now() + Duration::from_millis(2_000),
1133 });
1134 let instance = match instance {

Callers 1

run_oneFunction · 0.85

Calls 15

compile_moduleFunction · 0.85
take_poll_amtFunction · 0.85
YieldNClass · 0.85
OkFunction · 0.85
unwrap_instanceFunction · 0.85
to_storeMethod · 0.80
run_periodicallyMethod · 0.80
into_externMethod · 0.80
block_onFunction · 0.70
newFunction · 0.50
engineMethod · 0.45
cloneMethod · 0.45

Tested by

no test coverage detected