5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 17:52:29 +08:00
wails/v2/internal/frontend/desktop/linux/invoke.go
stffabi 2a0673f99f
[v2, linux] Improve switching to main thread for callbacks (#1392)
Make sure no pointers to the stack are passed to g_idle_add,
because at the time the callback gets executed on the
main thread, the pointer might be invalid.
Go might have reused the stack or grown the stack and the
pointer is invalid.

The concept used on Windows has been ported to Linux.
2022-05-31 20:28:37 +10:00

79 lines
1.1 KiB
Go

//go:build linux
// +build linux
package linux
/*
#cgo linux pkg-config: gtk+-3.0
#include <stdio.h>
#include "gtk/gtk.h"
extern gboolean invokeCallbacks(void *);
static inline void triggerInvokesOnMainThread() {
g_idle_add((GSourceFunc)invokeCallbacks, NULL);
}
*/
import "C"
import (
"runtime"
"sync"
"unsafe"
"golang.org/x/sys/unix"
)
var (
m sync.Mutex
mainTid int
dispatchq []func()
)
func invokeOnMainThread(f func()) {
if tryInvokeOnCurrentGoRoutine(f) {
return
}
m.Lock()
dispatchq = append(dispatchq, f)
m.Unlock()
C.triggerInvokesOnMainThread()
}
func tryInvokeOnCurrentGoRoutine(f func()) bool {
m.Lock()
mainThreadID := mainTid
m.Unlock()
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if mainThreadID != unix.Gettid() {
return false
}
f()
return true
}
//export invokeCallbacks
func invokeCallbacks(_ unsafe.Pointer) C.gboolean {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
m.Lock()
if mainTid == 0 {
mainTid = unix.Gettid()
}
q := append([]func(){}, dispatchq...)
dispatchq = []func(){}
m.Unlock()
for _, v := range q {
v()
}
return C.G_SOURCE_REMOVE
}