Repository navigation
go: fix exported-resource handle bookkeeping and use the standard generated-code header - #1746
Merged
dicej merged 3 commits intoOct 15, 2026
Conversation
For a resource this component exports, `resource.drop` on an own handle runs the destructor synchronously (the canonical ABI calls the dtor when the dropping instance implements the resource). The generated `resourceDtor<X>` already clears the handle, unpins the object and calls `OnDrop`, but `Drop()` then unpinned again and called `OnDrop` a second time. Rely on the destructor instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When an own handle of an exported resource is passed back into the component that exports it (e.g. `consume: func(x: x)`), the callee gets a new handle in its own table. `<Resource>FromOwnHandle` returned the object without recording that handle, so `self.handle` still held the one `TakeHandle` handed out earlier. `Drop()` then released a stale handle (possibly another object's) and the incoming handle was never dropped. Record it. The new `resource-own-roundtrip` runtime test passes two own handles back at once, so they cannot both reuse the slot handed out before; it fails without this change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Go tools recognize generated files by a line matching `^// Code generated .* DO NOT EDIT\.$` (https://go.dev/s/generatedcode). The previous `// Generated by `wit-bindgen` X. DO NOT EDIT!` header did not match, so linters, `gopls` and GitHub's diff view treated the bindings as hand-written. Stub files keep their header since they are meant to be edited. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sideeffffect
marked this pull request as ready for review
October 13, 2026 19:02
Contributor
Author
|
@asteurer could you have a look please? 🙏 |
asteurer
reviewed
Oct 15, 2026
asteurer
left a comment
Contributor
There was a problem hiding this comment.
Thanks @sideeffffect! I'll make some time tomorrow or Friday to look this over.
asteurer
approved these changes
Oct 15, 2026
asteurer
left a comment
Contributor
There was a problem hiding this comment.
Looks good to me! Below is a quick summary. @dicej if nothing looks amiss, do you mind merging?
1. OnDrop called twice
Confirmed bug. Per the Canonical ABI, canon_resource_drop calls the resource's rt.dtor() method which results in self.OnDrop() being called twice.
2. Incoming handle not recorded
Confirmed bug. <Resource>FromOwnHandle will sometimes store an outdated handle.
3. Go header convention
Great catch!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft: three small fixes to the Go generator for exported resources and the file header. I found them while using
wit-bindgen0.61.1 (throughcomponentize-go) in a real project, where I currently patch the generated code by hand.The variant-case vs. record name clash I also hit (
variant job-failure-policy { constant(job-failure-policy-constant) }) is already fixed onmainby #1717 (#1703), so this PR does not touch it.1.
Drop()on an exported resource callsOnDroptwiceFor a resource the component exports,
resource.dropon an own handle runs the destructor synchronously, because the dropping instance implements the resource. The generatedresourceDtor<X>already clears the handle, unpins the object and callsOnDrop.Drop()then unpinned again and calledOnDropa second time.2.
<Resource>FromOwnHandledoes not record the incoming handleWhen an own handle of an exported resource comes back into the exporting component (for example
consume: func(x: x)), the callee gets a new handle in its own table.XFromOwnHandlereturned the object but kept the oldself.handlethatTakeHandlehanded out earlier. SoDrop()released a stale handle (possibly another object's handle), and the incoming handle was never dropped.The existing
resourcesruntime test (consume) does not catch this, because there the incoming handle happens to reuse the slot that was handed out before. Bugs 1 and 2 also hid each other in a counter-based test: the doubleOnDropmade up for the destructor that never ran.3. Generated-code header does not match Go's convention
Go tools recognize generated files by a line matching
^// Code generated .* DO NOT EDIT\.$(https://go.dev/s/generatedcode). The old header did not match, sogopls, linters and GitHub's diff view treated the bindings as hand-written.Stub files (
--generate-stubs) keep their header, because they are meant to be edited.Tests
tests/runtime/resource-own-roundtrip(Go + Rust for bothrunnerandtest). It passes two own handles back at the same time, so they cannot both reuse the slot handed out before, and it checks the destructor count.panic: 1 not equal to 2.panic: 4 not equal to 2.tests::generated_files_have_go_generated_code_headerinwit-bindgen-go. It fails with the old header.Run locally with the patched Go 1.27.1 from CI:
cargo fmt --all -- --check,cargo clippy -p wit-bindgen-go --all-targets: cleancargo test -p wit-bindgen-go: 1 passedcargo run test --languages go tests/codegen ...: 218 passedcargo run test --languages rust,go tests/runtime ... --skip dylibs: 240 compiled, 184 runtime compositions passed. The skippedrust/dylibs*tests need wasi-sdk, which I don't have locally. I did not run the C runtime tests for the same reason.🤖 Generated with Claude Code