diff --git a/crates/wasmtime/src/runtime/component/concurrent.rs b/crates/wasmtime/src/runtime/component/concurrent.rs index 612ca91c9f..8d9bbec29b 100644 --- a/crates/wasmtime/src/runtime/component/concurrent.rs +++ b/crates/wasmtime/src/runtime/component/concurrent.rs @@ -890,7 +890,7 @@ impl ComponentInstance { Ok(()) } else { // In this case, the fiber suspended while holding on to its - // `*mut dyn VMStoret` instead of returning it to us. That + // `*mut dyn VMStore` instead of returning it to us. That // means we can't do anything else with the store (or self) // for now; the only thing we can do is suspend _our_ fiber // back up to the top level executor, which will resume us @@ -1485,6 +1485,8 @@ impl ComponentInstance { }, }; + let sync_caller = matches!(caller_info, CallerInfo::Sync { .. }); + let start = SendSyncPtr::new(NonNull::new(start).unwrap()); let return_ = SendSyncPtr::new(NonNull::new(return_).unwrap()); let old_task = self.guest_task().take(); @@ -1541,14 +1543,17 @@ impl ComponentInstance { )?; } let task = instance.guest_task().unwrap(); - if let ResultInfo::Stack { result_count } = &result_info { - match result_count { - 0 => {} - 1 => { - instance.get_mut(task)?.sync_result = Some(my_src[0]); - } - _ => unreachable!(), - } + if sync_caller { + instance.get_mut(task)?.sync_result = + Some(if let ResultInfo::Stack { result_count } = &result_info { + match result_count { + 0 => None, + 1 => Some(my_src[0]), + _ => unreachable!(), + } + } else { + None + }); } if old_task_rep.is_some() { let waitable = Waitable::Guest(task); @@ -1576,11 +1581,6 @@ impl ComponentInstance { if let Some(old_task) = old_task { self.get_mut(old_task)?.subtasks.insert(guest_task); - log::trace!( - "new guest task child of {}: {}", - old_task.rep(), - guest_task.rep() - ); }; *self.guest_task() = Some(guest_task); @@ -1714,7 +1714,11 @@ impl ComponentInstance { if let Some(storage) = storage { if let Some(result) = self.get_mut(guest_task)?.sync_result.take() { - storage[0] = MaybeUninit::new(result); + if let Some(result) = result { + storage[0] = MaybeUninit::new(result); + } + } else { + return Err(anyhow!(crate::Trap::NoAsyncResult)); } Ok(0) } else { @@ -2892,7 +2896,7 @@ struct GuestTask { deferred: Deferred, should_yield: bool, call_context: Option, - sync_result: Option, + sync_result: Option>, has_suspended: bool, context: [u32; 2], subtasks: HashSet>, diff --git a/tests/misc_testsuite/component-model-async/fused.wast b/tests/misc_testsuite/component-model-async/fused.wast index 7cf0a109a1..1a94397fea 100644 --- a/tests/misc_testsuite/component-model-async/fused.wast +++ b/tests/misc_testsuite/component-model-async/fused.wast @@ -51,8 +51,7 @@ (func (export "run") (alias export $lowerer "run")) ) -;; TODO: this requires async support in `wasmtime-wast`: -;;(assert_return (invoke "run")) +(assert_return (invoke "run")) ;; async lower -> async lift with callback (component @@ -105,8 +104,7 @@ (func (export "run") (alias export $lowerer "run")) ) -;; TODO: this requires async support in `wasmtime-wast`: -;;(assert_return (invoke "run")) +(assert_return (invoke "run")) ;; async lower -> sync lift (component @@ -152,8 +150,7 @@ (func (export "run") (alias export $lowerer "run")) ) -;; TODO: this requires async support in `wasmtime-wast`: -;;(assert_return (invoke "run")) +(assert_return (invoke "run")) ;; sync lower -> async lift without callback (component @@ -196,8 +193,7 @@ (func (export "run") (alias export $lowerer "run")) ) -;; TODO: this requires async support in `wasmtime-wast`: -;;(assert_return (invoke "run")) +(assert_return (invoke "run")) ;; sync lower -> async lift with callback (component @@ -244,5 +240,4 @@ (func (export "run") (alias export $lowerer "run")) ) -;; TODO: this requires async support in `wasmtime-wast`: -;;(assert_return (invoke "run")) +(assert_return (invoke "run")) diff --git a/tests/misc_testsuite/component-model-async/wait-forever.wast b/tests/misc_testsuite/component-model-async/wait-forever.wast new file mode 100644 index 0000000000..8989b1a4e5 --- /dev/null +++ b/tests/misc_testsuite/component-model-async/wait-forever.wast @@ -0,0 +1,56 @@ +;;! cm_async = true +;;! reference_types = true +;;! gc_types = true +;;! multi_memory = true + +(component + (component $child + (core module $libc (memory (export "memory") 1)) + (core instance $libc (instantiate $libc)) + + (core module $m + (import "" "waitable-set-new" (func $waitable-set-new (result i32))) + (func (export "run") (result i32) + call $waitable-set-new + i32.const 4 + i32.shl + i32.const 2 ;; CallbackCode.WAIT + i32.or + ) + + (func (export "cb") (param i32 i32 i32) (result i32) + unreachable) + ) + + (core func $waitable-set-new (canon waitable-set.new)) + + (core instance $i (instantiate $m + (with "" (instance + (export "waitable-set-new" (func $waitable-set-new)) + )) + )) + + (func (export "run") + (canon lift (core func $i "run") async (callback (func $i "cb")))) + ) + (instance $child (instantiate $child)) + + (core func $child-run (canon lower (func $child "run"))) + + (core module $m + (import "" "child-run" (func $child-run)) + + (func (export "run") + (call $child-run)) + ) + (core instance $i (instantiate $m + (with "" (instance + (export "child-run" (func $child-run)) + )) + )) + + (func (export "run") + (canon lift (core func $i "run"))) +) + +(assert_trap (invoke "run") "async-lifted export failed to produce a result")