Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions c/c.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,18 @@ func GoDeferData() Pointer

// -----------------------------------------------------------------------------

func ClosureData[ClosureT any](closure ClosureT) Pointer {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Document ClosureData's unsafe contract (GC lifetime + exported doc comment)

ClosureData is an exported function with no doc comment, unlike neighbors such as GoString (line 180). Beyond golint/godoc convention, the lifetime contract is non-obvious: new(ClosureT) allocates a Go-managed object returned as a bare unsafe.Pointer. Once handed to C, the GC no longer sees a typed reference, so if C retains the pointer past the last Go reference the backing object can be collected or moved, leaving a dangling pointer. Recommend a doc comment stating (1) the purpose and (2) that the caller must keep the returned Pointer's backing allocation reachable (e.g. via runtime.KeepAlive/runtime.Pinner) for as long as C uses it.

ret := new(ClosureT)
*ret = closure
return Pointer(ret)
}

func GoClosure[ClosureT any](data Pointer) (closure ClosureT) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Document GoClosure's unchecked type reinterpretation + nil precondition

GoClosure is exported with no doc comment and performs *(*ClosureT)(data), blindly reinterpreting data as *ClosureT. Because ClosureT is inferred independently at each call site and is invisible in the raw Pointer, a mismatch between the type used at ClosureData and here is silent memory corruption with no compiler/runtime guard. Additionally, a nil data (common for a C callback's opaque user-data slot) dereferences nil and crashes. Recommend a doc comment stating that data must originate from ClosureData with the same ClosureT and must be non-nil (and/or add an early nil guard).

return *(*ClosureT)(data)
}

// -----------------------------------------------------------------------------

//go:linkname AllocaSigjmpBuf llgo.sigjmpbuf
func AllocaSigjmpBuf() Pointer

Expand Down
Loading