From c989321509ca3db8902d048474e061f028cb5980 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Wed, 28 Aug 2024 21:07:16 -0700 Subject: [PATCH] runner.go: Don't cast a Go handle to a C void * Cgo handles passing pointers through C to another Go function with integer handles to the Go memory. However, it is not legal to cast this handle to a void * aux data in C. Doing this results in panics about invalid pointers on the stack in certain circumstances. Instead, we should pass a pointer to the handle and pin that in memory. It would probably also be safe to directly pin the Go function pointer and pass that rather than using the handle since it is an opaque blob to C. However, using a handle is the more generally correct solution and there is no need to get clever. --- llama/llama.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/llama/llama.go b/llama/llama.go index 0ffc2e35..896fcb37 100644 --- a/llama/llama.go +++ b/llama/llama.go @@ -163,7 +163,7 @@ type ModelParams struct { //export llamaProgressCallback func llamaProgressCallback(progress C.float, userData unsafe.Pointer) C.bool { - handle := cgo.Handle(userData) + handle := *(*cgo.Handle)(userData) callback := handle.Value().(func(float32)) callback(float32(progress)) return true @@ -190,8 +190,12 @@ func LoadModelFromFile(modelPath string, params ModelParams) *Model { handle := cgo.NewHandle(params.Progress) defer handle.Delete() + var handlePin runtime.Pinner + handlePin.Pin(&handle) + defer handlePin.Unpin() + cparams.progress_callback = C.llama_progress_callback(C.llamaProgressCallback) - cparams.progress_callback_user_data = unsafe.Pointer(handle) + cparams.progress_callback_user_data = unsafe.Pointer(&handle) } return &Model{c: C.llama_load_model_from_file(C.CString(modelPath), cparams)}