Open Loafter opened 6 years ago
Hi, make sure the GFX goroutine (where GL initialisation, Nuklear initialisation are happening) is locked to the thread using runtime.LockOSThread()
If your loop is in the main goroutine (as in example), the following code is sufficient
func init() {
runtime.LockOSThread()
}
If this doesn't help, I'd need the sample code to reproduce this error.
this is minimal code for reproduce this effect please be patient, it hapen randomly. For me it take 20 times click for reproduce this effect Windows 7 x64 go1.9 package main
package main
import (
"github.com/go-gl/gl/v3.2-core/gl"
"github.com/go-gl/glfw/v3.2/glfw"
"github.com/golang-ui/nuklear/nk"
"log"
"os/exec"
"runtime"
)
const (
maxVertexBuffer = 512 * 1024
maxElementBuffer = 128 * 1024
)
func main() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
winWidth := 500
winHeight := 200
win := initWindow(winWidth, winHeight)
win.MakeContextCurrent()
log.Printf("glfw: created window %dx%d", winWidth, winHeight)
ctx := InitNK(winWidth, winHeight, win)
initFont(ctx)
for !win.ShouldClose() {
glfw.WaitEvents()
nk.NkPlatformNewFrame()
w, h := win.GetSize()
bounds := nk.NkRect(0, 0, float32(w), float32(h))
update := nk.NkBegin(ctx, "Demo", bounds, nk.WindowNoScrollbar)
if update > 0 {
nk.NkLayoutRowDynamic(ctx, 30, 2)
nk.NkLabel(ctx, "Test:", nk.TextCentered)
if nk.NkButtonLabel(ctx, "Click here") > 0 {
out, err := exec.Command("ping", "ya.ru", "-n", "2").Output()
log.Println(string(out), err)
}
}
nk.NkEnd(ctx)
glRender(win)
}
}
func glRender(win *glfw.Window) {
width, height := win.GetSize()
gl.Viewport(0, 0, int32(width), int32(height))
gl.Clear(gl.COLOR_BUFFER_BIT)
nk.NkPlatformRender(nk.AntiAliasingOn, maxVertexBuffer, maxElementBuffer)
win.SwapBuffers()
}
func initFont(ctx *nk.Context) {
atlas := nk.NewFontAtlas()
nk.NkFontStashBegin(&atlas)
sansFont := nk.NkFontAtlasAddDefault(atlas, 30, nil)
nk.NkFontStashEnd()
if sansFont != nil {
nk.NkStyleSetFont(ctx, sansFont.Handle())
}
}
func InitNK(winWidth int, winHeight int, win *glfw.Window) *nk.Context {
if err := gl.Init(); err != nil {
log.Fatal(err)
}
gl.Viewport(0, 0, int32(winWidth), int32(winHeight))
ctx := nk.NkPlatformInit(win, nk.PlatformInstallCallbacks)
return ctx
}
func initWindow(winWidth int, winHeight int) *glfw.Window {
if err := glfw.Init(); err != nil {
log.Fatal(err)
}
glfw.WindowHint(glfw.ContextVersionMajor, 3)
glfw.WindowHint(glfw.ContextVersionMinor, 2)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
win, err := glfw.CreateWindow(winWidth, winHeight, "DICOM CD Writer GUI", nil, nil)
if err != nil {
log.Fatal(err)
}
return win
}
Any suggestions?
I don't know the root cause but probably you can avoid it by using GOGC=off
.
@oov not an option in long run.. but can be harmless to use for now :(
@Loafter sorry, got some work to do. I have to boot my Windows 10 machine, because I cannot reproduce the issue on OS X. Make sure you're on HEAD master. Because in the latest commit I disabled memory-related features that caused crashes on OS X.
I'm balancing between a crash and possible memory leaks, don't want to get those leaks back.
same problem at this time i used Windows 10 x64 go1.9.1 windows/amd64 gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 7.2.0 May be problem with posix thread model in gcc?
Exception 0xc0000005 0x8 0xc04200a2ca 0xc04200a2ca
PC=0xc04200a2ca
signal arrived during external code execution
github.com/golang-ui/nuklear/nk._Cfunc_nk_convert(0x5c81d40, 0x5c86e50, 0x5ccca00, 0x5ccc800, 0x5cc7f20, 0xc000000000)
github.com/golang-ui/nuklear/nk/_obj/_cgo_gotypes.go:3065 +0x54
github.com/golang-ui/nuklear/nk.NkConvert.func1(0x5c81d40, 0x5c86e50, 0x5ccca00, 0x5ccc800, 0x5cc7f20, 0x20000)
C:/Users/alex/go/src/github.com/golang-ui/nuklear/nk/nk.go:155 +0x167
github.com/golang-ui/nuklear/nk.NkConvert(0x5c81d40, 0x5c86e50, 0x5ccca00, 0x5ccc800, 0xc042031dd8, 0xc042020000)
C:/Users/alex/go/src/github.com/golang-ui/nuklear/nk/nk.go:155 +0x68
github.com/golang-ui/nuklear/nk.NkPlatformRender(0x1, 0x80000, 0x20000)
C:/Users/alex/go/src/github.com/golang-ui/nuklear/nk/impl_glfw_gl3.go:99 +0x448
main.glRender(0xc042072000)
C:/Users/alex/go/src/crashtest/main.go:53 +0x7b
I've found the root cause.
package main
import (
"log"
"os/exec"
"runtime"
"github.com/go-gl/gl/v3.2-core/gl"
"github.com/go-gl/glfw/v3.2/glfw"
"github.com/golang-ui/nuklear/nk"
)
const (
maxVertexBuffer = 512 * 1024
maxElementBuffer = 128 * 1024
)
func main() {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
winWidth := 500
winHeight := 200
win := initWindow(winWidth, winHeight)
win.MakeContextCurrent()
log.Printf("glfw: created window %dx%d", winWidth, winHeight)
ctx := InitNK(winWidth, winHeight, win)
fontHandle := initFont(ctx)
for !win.ShouldClose() {
glfw.WaitEvents()
nk.NkPlatformNewFrame()
w, h := win.GetSize()
bounds := nk.NkRect(0, 0, float32(w), float32(h))
update := nk.NkBegin(ctx, "Demo", bounds, nk.WindowNoScrollbar)
if update > 0 {
nk.NkLayoutRowDynamic(ctx, 30, 2)
nk.NkLabel(ctx, "Test:", nk.TextCentered)
if nk.NkButtonLabel(ctx, "Click here") > 0 {
out, err := exec.Command("ping", "ya.ru", "-n", "2").Output()
log.Println(string(out), err)
}
}
nk.NkEnd(ctx)
glRender(win)
}
runtime.KeepAlive(fontHandle) // <-- We have to keep this.
}
func glRender(win *glfw.Window) {
width, height := win.GetSize()
gl.Viewport(0, 0, int32(width), int32(height))
gl.Clear(gl.COLOR_BUFFER_BIT)
nk.NkPlatformRender(nk.AntiAliasingOn, maxVertexBuffer, maxElementBuffer)
win.SwapBuffers()
}
func initFont(ctx *nk.Context) *nk.UserFont {
atlas := nk.NewFontAtlas()
nk.NkFontStashBegin(&atlas)
sansFont := nk.NkFontAtlasAddDefault(atlas, 30, nil)
nk.NkFontStashEnd()
if sansFont != nil {
sansFontHandle := sansFont.Handle()
nk.NkStyleSetFont(ctx, sansFontHandle)
return sansFontHandle
}
return nil
}
func InitNK(winWidth int, winHeight int, win *glfw.Window) *nk.Context {
if err := gl.Init(); err != nil {
log.Fatal(err)
}
gl.Viewport(0, 0, int32(winWidth), int32(winHeight))
ctx := nk.NkPlatformInit(win, nk.PlatformInstallCallbacks)
return ctx
}
func initWindow(winWidth int, winHeight int) *glfw.Window {
if err := glfw.Init(); err != nil {
log.Fatal(err)
}
glfw.WindowHint(glfw.ContextVersionMajor, 3)
glfw.WindowHint(glfw.ContextVersionMinor, 2)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
win, err := glfw.CreateWindow(winWidth, winHeight, "DICOM CD Writer GUI", nil, nil)
if err != nil {
log.Fatal(err)
}
return win
}
oov looks like you solve my problem! Thanks a lot)
I am having the same crash but in a different scenario, maybe this will shed some light on the issue (also I am stuck).
Here I add the example GUI to my project: https://github.com/jakecoffman/tanklets/commit/baf4e7e5e731e2e2ce0dbeb12fc2edffcf5dd8e8
When I run cmd/testlet
, which starts the server and two clients, it crashes immediately or sometimes after I drag a window. Sometimes the other window crashes, not the one I am dragging in!
If I modify cmd/testlet
to only launch one client then it doesn't crash... which seems to indicate there is some shared state between the two GUI processes somehow?!
Also I tried @oov's fix above but that didn't seem to help the crashing.
Any ideas? Happens on Windows 10 and OSX.
My mistake, @oov's fix does fix it for me too!
So the fix is to add:
runtime.KeepAlive(fontHandle) // <-- We have to keep this.
Do you know why this is required?
Because C references to Go's *nk.UserFont
pointer that passed at nk.NkStyleSetFont
.
So it is necessary to prevent it being collected by GC.
I creating gui application with multiple goroute functionality. Some of goroute execute another application (exec.Command) with parsing output. At this momen application have only one goroute for rendering and dispatch event. When i try dispatch event application raise exeption
signal arrived during external code execution