diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 4fa62e5..94a2799 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -497,11 +497,14 @@ mod async_ { ReturnStyle::Result => vec![result], }; - let mut call = MyCall::new(results); - func.call_task_return(&mut call); + // `task.return` traps while any borrow lent to this task is still + // outstanding, so drop them first. if borrows != 0 { release_borrows(py, *unsafe { Box::from_raw(borrows as *mut Vec) }); } + + let mut call = MyCall::new(results); + func.call_task_return(&mut call); } #[pyo3::pyfunction] diff --git a/src/test/python_source/app.py b/src/test/python_source/app.py index 6d4a74f..7161873 100644 --- a/src/test/python_source/app.py +++ b/src/test/python_source/app.py @@ -253,6 +253,9 @@ class Tests(tests.WorldExports): def test_resource_borrow_import(self, v: int) -> int: return resource_borrow_import.foo(resource_borrow_import.Thing(v + 1)) + 4 + async def test_resource_borrow_import_async(self, t: resource_borrow_import.Thing) -> int: + return resource_borrow_import.foo(t) + 4 + def test_resource_alias(self, things: List[imports.resource_alias1.Thing]) -> List[imports.resource_alias1.Thing]: return things diff --git a/src/test/tests.rs b/src/test/tests.rs index 6929fa2..09aefd0 100644 --- a/src/test/tests.rs +++ b/src/test/tests.rs @@ -384,6 +384,31 @@ fn resource_borrow_import() -> Result<()> { }) } +#[test] +fn resource_borrow_import_async_export() -> Result<()> { + // An async export that is lent a borrow of an imported resource must release + // it before `task.return`, or the host traps with "borrow handles still + // remain at the end of the call". + TESTER.test(|world, store, runtime| { + runtime.block_on(async { + let thing = store.data_mut().ctx().table.push(ThingU32(42))?; + + assert_eq!( + 42 + 3 + 4, + store + .run_concurrent(async |store| { + world + .call_test_resource_borrow_import_async(store, thing) + .await + }) + .await?? + ); + + Ok(()) + }) + }) +} + #[test] fn resource_borrow_export() -> Result<()> { TESTER.test(|world, store, runtime| { diff --git a/src/test/wit/tests.wit b/src/test/wit/tests.wit index cfe233f..0ef3070 100644 --- a/src/test/wit/tests.wit +++ b/src/test/wit/tests.wit @@ -186,6 +186,7 @@ interface empty-resource { world tests { use resource-alias1.{thing}; use resource-floats.{float}; + use resource-borrow-import.{thing as imported-thing}; export simple-export; import simple-import-and-export; @@ -230,6 +231,8 @@ world tests { export test-resource-borrow-import: func(v: u32) -> u32; + export test-resource-borrow-import-async: async func(t: borrow) -> u32; + export test-resource-alias: func(things: list) -> list; export add: func(a: borrow, b: borrow) -> own;