webview / webview_go

Go language bindings for the webview library.
MIT License
176 stars 27 forks source link

segfault running webview.Eval in goroutine a lot #26

Closed Le0Developer closed 5 months ago

Le0Developer commented 5 months ago

Ran into this segfault when my app did an oopsie and recursively called a binding that spawned a goroutine which eval'ed itself.

package main

import (
    "fmt"

    webview "github.com/webview/webview_go"
)

func main() {
    w := webview.New(true)
    defer w.Destroy()
    w.SetTitle("Basic Example")
    w.SetSize(480, 320, webview.HintNone)
    w.SetHtml("<button onclick=\"exec()\">Click</button>")
    dept := 0
    w.Bind("exec", func() {
        go func() {
            fmt.Println("exec", dept)
            dept++
            // w.Dispatch(func() {
                w.Eval("setTimeout(window.exec, 1)")
            // })
        }()
    })
    w.Run()
}

Works

  1. without go func() {
  2. with w.Dispatch(func() {

Crash log:

Long log ``` exec 604 SIGSEGV: segmentation violation PC=0x188041420 m=5 sigcode=2 signal arrived during cgo execution goroutine 628 [syscall]: runtime.cgocall(0x1049b7b30, 0x14000127ed8) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/cgocall.go:157 +0x44 fp=0x14000127ea0 sp=0x14000127e60 pc=0x10 49004c4 github.com/webview/webview_go._Cfunc_webview_eval(0x600000320000, 0x600002046f80) _cgo_gotypes.go:162 +0x30 fp=0x14000127ed0 sp=0x14000127ea0 pc=0x1049b5820 github.com/webview/webview_go.(*webview).Eval.func2(0x1049c0a62?, 0x1a?) /Users/leodev/go/pkg/mod/github.com/webview/webview_go@v0.0.0-20230901181450-5a14030a9070/webview.go:199 +0x50 fp =0x14000127f10 sp=0x14000127ed0 pc=0x1049b6390 github.com/webview/webview_go.(*webview).Eval(0x104a0a1c8?, {0x1049c0a62?, 0x14000127fa8?}) /Users/leodev/go/pkg/mod/github.com/webview/webview_go@v0.0.0-20230901181450-5a14030a9070/webview.go:199 +0x68 fp =0x14000127f60 sp=0x14000127f10 pc=0x1049b62e8 main.main.func1.1() /Users/leodev/p/go/main.go:21 +0xb8 fp=0x14000127fd0 sp=0x14000127f60 pc=0x1049b7928 runtime.goexit() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000127fd0 sp=0x14000127fd0 pc=0x1 0495db24 created by main.main.func1 in goroutine 1 /Users/leodev/p/go/main.go:17 +0x9c goroutine 1 [syscall, locked to thread]: runtime.cgocall(0x1049b7bb0, 0x14000117e58) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/cgocall.go:157 +0x44 fp=0x14000117e20 sp=0x14000117de0 pc=0x10 49004c4 github.com/webview/webview_go._Cfunc_webview_run(0x600000320000) _cgo_gotypes.go:233 +0x30 fp=0x14000117e50 sp=0x14000117e20 pc=0x1049b5940 github.com/webview/webview_go.(*webview).Run.func1(0x60000222c650?) /Users/leodev/go/pkg/mod/github.com/webview/webview_go@v0.0.0-20230901181450-5a14030a9070/webview.go:157 +0x40 fp =0x14000117e90 sp=0x14000117e50 pc=0x1049b5e20 github.com/webview/webview_go.(*webview).Run(0x1400004a020?) /Users/leodev/go/pkg/mod/github.com/webview/webview_go@v0.0.0-20230901181450-5a14030a9070/webview.go:157 +0x1c fp =0x14000117eb0 sp=0x14000117e90 pc=0x1049b5dbc main.main() /Users/leodev/p/go/main.go:25 +0x16c fp=0x14000117f30 sp=0x14000117eb0 pc=0x1049b776c runtime.main() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:267 +0x2bc fp=0x14000117fd0 sp=0x14000117f30 pc=0x1049 3157c runtime.goexit() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000117fd0 sp=0x14000117fd0 pc=0x1 0495db24 goroutine 2 [force gc (idle)]: runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:398 +0xc8 fp=0x14000046f90 sp=0x14000046f70 pc=0x10493 19a8 runtime.goparkunlock(...) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:404 runtime.forcegchelper() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:322 +0xb8 fp=0x14000046fd0 sp=0x14000046f90 pc=0x10493 1838 runtime.goexit() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000046fd0 sp=0x14000046fd0 pc=0x1 0495db24 created by runtime.init.6 in goroutine 1 /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:310 +0x24 goroutine 18 [GC sweep wait]: runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:398 +0xc8 fp=0x14000042760 sp=0x14000042740 pc=0x10493 19a8 runtime.goparkunlock(...) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:404 runtime.bgsweep(0x0?) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgcsweep.go:280 +0xa0 fp=0x140000427b0 sp=0x14000042760 pc=0x1 0491eb50 runtime.gcenable.func1() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgc.go:200 +0x28 fp=0x140000427d0 sp=0x140000427b0 pc=0x104913 648 runtime.goexit() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/asm_arm64.s:1197 +0x4 fp=0x140000427d0 sp=0x140000427d0 pc=0x1 0495db24 created by runtime.gcenable in goroutine 1 /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgc.go:200 +0x6c goroutine 19 [GC scavenge wait]: runtime.gopark(0x1400008e000?, 0x1049e4550?, 0x1?, 0x0?, 0x140000824e0?) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:398 +0xc8 fp=0x14000042f50 sp=0x14000042f30 pc=0x10493 19a8 runtime.goparkunlock(...) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:404 runtime.(*scavengerState).park(0x104aa1640) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgcscavenge.go:425 +0x5c fp=0x14000042f80 sp=0x14000042f50 pc= 0x10491c3fc runtime.bgscavenge(0x0?) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgcscavenge.go:653 +0x44 fp=0x14000042fb0 sp=0x14000042f80 pc= 0x10491c954 runtime.gcenable.func2() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgc.go:201 +0x28 fp=0x14000042fd0 sp=0x14000042fb0 pc=0x104913 5e8 runtime.goexit() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000042fd0 sp=0x14000042fd0 pc=0x1 0495db24 created by runtime.gcenable in goroutine 1 /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mgc.go:201 +0xac goroutine 3 [finalizer wait]: runtime.gopark(0x140000465c8?, 0x104996c10?, 0x0?, 0x0?, 0x1049bd990?) /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/proc.go:398 +0xc8 fp=0x14000046580 sp=0x14000046560 pc=0x10493 19a8 runtime.runfinq() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mfinal.go:193 +0x108 fp=0x140000467d0 sp=0x14000046580 pc=0x10 49126f8 runtime.goexit() /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/asm_arm64.s:1197 +0x4 fp=0x140000467d0 sp=0x140000467d0 pc=0x1 0495db24 created by runtime.createfing in goroutine 1 /opt/homebrew/Cellar/go/1.21.6/libexec/src/runtime/mfinal.go:163 +0x80 r0 0x600001522dc0 r1 0x1d767a60e r2 0x600001522dc0 r3 0x2 r4 0x4 r5 0xf60 r6 0x60000204c860 r7 0x0 r8 0xde9932f2dc0 r9 0xcb850001df096060 r10 0x6ae1600001522dc0 r11 0x1dec053bf r12 0x0 r13 0x1ff800 r14 0xde9932f2dc0 r15 0xde9932f2dc0 r16 0xde9932f2dc0 r17 0x1e7cb24c8 r18 0x0 r19 0x16d522800 r20 0x600002e2e3a0 r21 0x600001522dc0 r22 0x600001522dc0 r23 0x1540802d0 r24 0x154108200 r25 0x154004200 r26 0x154100aa0 r27 0x29 r28 0x3 r29 0x16d5227f0 lr 0x18861ca3c sp 0x16d522790 pc 0x188041420 fault 0xde9932f2dd0 exit status 2 ```
SteffenL commented 5 months ago

When you use goroutines then you should use w.Dispatch() to get back onto the thread where you can interact with the underlying browser engine safely. Once you've sorted that out then feel free to give us an update if you have more issues.

Le0Developer commented 5 months ago

Ah, thanks. It's not quite obvious that (to me at least) Eval is tweaking the native window as described in Dispatch.

You normally do not need to call this function, unless you want to tweak the native window.

Might benefit from some clarification.

SteffenL commented 5 months ago

That's a good point! We should investigate whether that comment is accurate.