Skip to content

Commit a555dc7

Browse files
authored
fix(go): prevent GC finalizer on borrowed resource handles (#1539)
* chore: add dev-dependencies for integration tests Add wit-bindgen-core, wit-bindgen-rust, wit-bindgen-go, and wit-parser as workspace dev-dependencies to support integration test files. * fix(go): prevent GC finalizer on borrowed resource handles FromBorrowHandle for imported resources was incorrectly delegating to FromOwnHandle, which registers a GC finalizer via runtime.AddCleanup. This violates the Component Model specification: borrowed handles are not owned by the callee, so the callee must not drop them. When Go's garbage collector ran, it would drop borrowed handles through the finalizer, corrupting the host's resource table. Fix FromBorrowHandle to create a handle object directly without registering a GC finalizer, preserving the correct ownership semantics.
1 parent 434322d commit a555dc7

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

crates/go/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2589,7 +2589,8 @@ func {camel}FromOwnHandle(handleValue int32) *{camel} {{
25892589
}}
25902590
25912591
func {camel}FromBorrowHandle(handleValue int32) *{camel} {{
2592-
return {camel}FromOwnHandle(handleValue)
2592+
handle := wit_runtime.MakeHandle(handleValue)
2593+
return &{camel}{{handle}}
25932594
}}
25942595
"#
25952596
);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package export_wit_world
2+
3+
import (
4+
"fmt"
5+
test "wit_component/test_resource_borrow_to_test"
6+
)
7+
8+
func Run() {
9+
thing := test.MakeThing(42)
10+
defer thing.Drop()
11+
12+
result := test.Foo(thing)
13+
assertEqual(result, uint32(42+1+2))
14+
}
15+
16+
func assertEqual[T comparable](a T, b T) {
17+
if a != b {
18+
panic(fmt.Sprintf("%v not equal to %v", a, b))
19+
}
20+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package export_test_resource_borrow_to_test
2+
3+
import (
4+
"runtime"
5+
)
6+
7+
type Thing struct {
8+
pinner runtime.Pinner
9+
handle int32
10+
val uint32
11+
}
12+
13+
func (self *Thing) OnDrop() {}
14+
15+
func MakeThing(v uint32) *Thing {
16+
return &Thing{runtime.Pinner{}, 0, v + 1}
17+
}
18+
19+
func Foo(v *Thing) uint32 {
20+
return v.val + 2
21+
}

0 commit comments

Comments
 (0)