Skip to content

Commit a14fff4

Browse files
committed
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 71563e5 commit a14fff4

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,3 @@ csharp = ['dep:wit-bindgen-csharp']
119119
csharp-mono = ['csharp']
120120
moonbit = ['dep:wit-bindgen-moonbit']
121121
async = []
122-
123-
[dev-dependencies]
124-
wit-bindgen-core = { workspace = true }
125-
wit-bindgen-rust = { workspace = true }
126-
wit-bindgen-go = { workspace = true }
127-
wit-parser = { workspace = true }

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)