Skip to content

Commit a526e1d

Browse files
authored
fixes: #345 InvokeMethodWithReply segfault (#382)
* fixes: #345 InvokeMethodWithReply segfault The callback function used to retrieve the value of the reply was free-ed by the Golang GC. This was quite hard to fix, had to uses runtime.KeepAlive on a struct that contains the callback function. runtime.KeepAlive, ensures that the object is not freed, and its finalizer is not run, before the point in the program where KeepAlive is called. Since the returned value is obtained with the callback function, I used the `defer` keyword to make the function as not used for the gc once we have the reply value. * adress PR comment
1 parent 58932d4 commit a526e1d

File tree

3 files changed

+16
-8
lines changed

3 files changed

+16
-8
lines changed

embedder/embedder.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,17 +346,20 @@ func (flu *FlutterEngine) MarkExternalTextureFrameAvailable(textureID int64) Res
346346

347347
// DataCallback is a function called when a PlatformMessage response send back
348348
// to the embedder.
349-
type DataCallback func(binaryReply []byte)
349+
type DataCallback struct {
350+
// Handle func
351+
Handle func(binaryReply []byte)
352+
}
350353

351354
// CreatePlatformMessageResponseHandle creates a platform message response
352355
// handle that allows the embedder to set a native callback for a response to a
353356
// message.
354357
// Must be collected via `ReleasePlatformMessageResponseHandle` after the call
355358
// to `SendPlatformMessage`.
356-
func (flu *FlutterEngine) CreatePlatformMessageResponseHandle(callback DataCallback) (PlatformMessageResponseHandle, error) {
359+
func (flu *FlutterEngine) CreatePlatformMessageResponseHandle(callback *DataCallback) (PlatformMessageResponseHandle, error) {
357360
var responseHandle *C.FlutterPlatformMessageResponseHandle
358361

359-
callbackPointer := uintptr(unsafe.Pointer(&callback))
362+
callbackPointer := uintptr(unsafe.Pointer(callback))
360363
defer func() {
361364
runtime.KeepAlive(callbackPointer)
362365
}()

embedder/embedder_proxy.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,6 @@ func proxy_post_task_callback(task C.FlutterTask, targetTimeNanos C.uint64_t, us
9797
//export proxy_desktop_binary_reply
9898
func proxy_desktop_binary_reply(data *C.uint8_t, dataSize C.size_t, userData unsafe.Pointer) {
9999
callbackPointer := *(*uintptr)(userData)
100-
handler := *(*DataCallback)(unsafe.Pointer(callbackPointer))
101-
handler(C.GoBytes(unsafe.Pointer(data), C.int(dataSize)))
100+
callback := (*DataCallback)(unsafe.Pointer(callbackPointer))
101+
callback.Handle(C.GoBytes(unsafe.Pointer(data), C.int(dataSize)))
102102
}

messenger.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package flutter
33
import (
44
"errors"
55
"fmt"
6+
"runtime"
67
"sync"
78

89
"github.com/go-flutter-desktop/go-flutter/embedder"
@@ -37,9 +38,13 @@ func newMessenger(engine *embedder.FlutterEngine) *messenger {
3738
func (m *messenger) SendWithReply(channel string, binaryMessage []byte) (binaryReply []byte, err error) {
3839
reply := make(chan []byte)
3940
defer close(reply)
40-
responseHandle, err := m.engine.CreatePlatformMessageResponseHandle(func(binaryMessage []byte) {
41-
reply <- binaryMessage
42-
})
41+
callbackHandle := &embedder.DataCallback{
42+
Handle: func(binaryMessage []byte) {
43+
reply <- binaryMessage
44+
},
45+
}
46+
defer runtime.KeepAlive(callbackHandle)
47+
responseHandle, err := m.engine.CreatePlatformMessageResponseHandle(callbackHandle)
4348
if err != nil {
4449
return nil, err
4550
}

0 commit comments

Comments
 (0)