Skip to content

Commit

Permalink
Go: use cgo.Handle to pass channel pointers to Rust and back to Go
Browse files Browse the repository at this point in the history
Fixes #3207

Passing uintptr(unsafe.Pointer) to rust and back to Go can break
the cgo pointer passing rules. Use cgo.Handle instead.

Signed-off-by: Rueian <[email protected]>
  • Loading branch information
rueian committed Feb 19, 2025
1 parent ae6a53c commit 111af00
Showing 1 changed file with 11 additions and 9 deletions.
20 changes: 11 additions & 9 deletions go/api/base_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ package api
// #cgo darwin,arm64 LDFLAGS: -L${SRCDIR}/../rustbin/aarch64-apple-darwin
// #include "../lib.h"
//
// void successCallback(void *channelPtr, struct CommandResponse *message);
// void failureCallback(void *channelPtr, char *errMessage, RequestErrorType errType);
// void successCallback(uintptr_t channelPtr, struct CommandResponse *message);
// void failureCallback(uintptr_t channelPtr, char *errMessage, RequestErrorType errType);
import "C"

import (
"fmt"
"math"
"runtime/cgo"
"strconv"
"unsafe"

Expand Down Expand Up @@ -51,17 +52,17 @@ type payload struct {
}

//export successCallback
func successCallback(channelPtr unsafe.Pointer, cResponse *C.struct_CommandResponse) {
func successCallback(channelPtr C.uintptr_t, cResponse *C.struct_CommandResponse) {
response := cResponse
resultChannel := *(*chan payload)(channelPtr)
resultChannel := *(cgo.Handle(channelPtr).Value().(*chan payload))
resultChannel <- payload{value: response, error: nil}
}

//export failureCallback
func failureCallback(channelPtr unsafe.Pointer, cErrorMessage *C.char, cErrorType C.RequestErrorType) {
func failureCallback(channelPtr C.uintptr_t, cErrorMessage *C.char, cErrorType C.RequestErrorType) {
defer C.free_error_message(cErrorMessage)
msg := C.GoString(cErrorMessage)
resultChannel := *(*chan payload)(channelPtr)
resultChannel := *(cgo.Handle(channelPtr).Value().(*chan payload))
resultChannel <- payload{value: nil, error: errors.GoError(uint32(cErrorType), msg)}
}

Expand Down Expand Up @@ -209,9 +210,6 @@ func (client *baseClient) executeCommandWithRoute(
argLengthsPtr = &argLengths[0]
}

resultChannel := make(chan payload)
resultChannelPtr := uintptr(unsafe.Pointer(&resultChannel))

var routeBytesPtr *C.uchar = nil
var routeBytesCount C.uintptr_t = 0
if route != nil {
Expand All @@ -228,6 +226,9 @@ func (client *baseClient) executeCommandWithRoute(
routeBytesPtr = (*C.uchar)(C.CBytes(msg))
}

resultChannel := make(chan payload)
resultChannelPtr := cgo.NewHandle(&resultChannel)

C.command(
client.coreClient,
C.uintptr_t(resultChannelPtr),
Expand All @@ -239,6 +240,7 @@ func (client *baseClient) executeCommandWithRoute(
routeBytesCount,
)
payload := <-resultChannel
resultChannelPtr.Delete()
if payload.error != nil {
return nil, payload.error
}
Expand Down

0 comments on commit 111af00

Please sign in to comment.