jonegil / gui-with-gio

Tutorials for Gio, the GUI framework in Go.
https://jonegil.github.io/gui-with-gio/
Other
193 stars 40 forks source link

panic: runtime error: invalid memory address or nil pointer dereference #17

Closed roborobs1023 closed 2 years ago

roborobs1023 commented 2 years ago

Getting the following error when I try to run the Eggtimer Blank window. The window runs briefly and then immediately closes. I can run the hello test from gioui.org perfectly. so don't think it's a missing install.

`panic: runtime error: invalid memory address or nil pointer dereference [signal 0xc0000005 code=0x0 addr=0x10 pc=0xb0b91a]

goroutine 8 [running, locked to thread]: gioui.org/app.(*Window).processEvent(0xc00020a000, {0xc44948, 0xc000206090}, {0xc42158?, 0xc000292000?})`

russoj88 commented 2 years ago

Can you add some context? OS, go version, command used to run, etc.

I have go 1.18 installed and it worked on Linux.

rngoodner commented 2 years ago

I get the same error on chapter 1 of the tutorial. I am using Go 1.18 on Ubuntu 18.04.

the error:

~/programming/learngio$ go run main.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x653afa]

goroutine 21 [running]:
gioui.org/app.(*Window).processEvent(0xc00023c000, {0x7f74d8, 0xc0000d8500}, {0x7f4a78?, 0xc0000d1110?})
    /home/rngoodn/go/pkg/mod/gioui.org@v0.0.0-20220328161522-75d487fa34b1/app/window.go:759 +0x47a
gioui.org/app.(*callbacks).Event(0xc00023c4a0, {0x7f4a78?, 0xc0000d1110?})
    /home/rngoodn/go/pkg/mod/gioui.org@v0.0.0-20220328161522-75d487fa34b1/app/window.go:426 +0x14d
gioui.org/app.(*x11Window).loop(0xc0000d8500)
    /home/rngoodn/go/pkg/mod/gioui.org@v0.0.0-20220328161522-75d487fa34b1/app/os_x11.go:451 +0x35b
gioui.org/app.newX11Window.func12()
    /home/rngoodn/go/pkg/mod/gioui.org@v0.0.0-20220328161522-75d487fa34b1/app/os_x11.go:821 +0x1a5
created by gioui.org/app.newX11Window
    /home/rngoodn/go/pkg/mod/gioui.org@v0.0.0-20220328161522-75d487fa34b1/app/os_x11.go:813 +0x8f5
exit status 2

main.go

package main

import (
    "gioui.org/app"
)

func main() {
    go func() {
            // create new window
            w := app.NewWindow()

            // listen for events in the window
            for range w.Events() {
            }
    }()

    app.Main()
}

go.mod:

module learngio

go 1.18

require gioui.org v0.0.0-20220328161522-75d487fa34b1

require (
    gioui.org/cpu v0.0.0-20210817075930-8d6a761490d2 // indirect
    gioui.org/shader v1.0.6 // indirect
    github.com/benoitkugler/textlayout v0.0.10 // indirect
    github.com/gioui/uax v0.2.1-0.20220325163150-e3d987515a12 // indirect
    github.com/go-text/typesetting v0.0.0-20220112121102-58fe93c84506 // indirect
    golang.org/x/exp v0.0.0-20210722180016-6781d3edade3 // indirect
    golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d // indirect
    golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect
    golang.org/x/text v0.3.6 // indirect
)
rngoodner commented 2 years ago

Without a full understanding what I am doing yet... I have tried merging the egg timer tutorial (chapter 2) and the Hello, Gio tutorial (https://gioui.org/doc/learn/get-started). Here is the minimum amount of code that I have been able to get running in hopes it helps narrow down the issue.

package main

import (
    "log"
    "os"

    "gioui.org/app"
    "gioui.org/io/system"
    "gioui.org/layout"
    "gioui.org/op"
    "gioui.org/unit"
)

func run(w *app.Window) error {
    var ops op.Ops
    for {
            e := <-w.Events()
            switch e := e.(type) {
            case system.DestroyEvent:
                        return e.Err
            case system.FrameEvent:
                        gtx := layout.NewContext(&ops, e)
                        e.Frame(gtx.Ops)
            }
    }
}

func main() {
    go func() {
            w := app.NewWindow(
                        app.Title("Egg timer"),
                        app.Size(unit.Dp(400), unit.Dp(600)),
            )
            err := run(w)
            if err != nil {
                        log.Fatal(err)
            }
            os.Exit(0)
    }()
    app.Main()
}
rngoodner commented 2 years ago

I also found that Chapter 3 runs as written without errors, but does not exit when the gui is closed. With this new information I stripped back Chapter 3 to recreate a working Chapter 2. It seems os.Exit(0) is needed to exit properly, and something related to ops and gtx is needed to prevent the the nil pointer dereference. The factored out run() function used in my last comment inhereted from the Hello, Gio tutorial does not seem to matter.

package main

import (
    "os"

    "gioui.org/app"
    "gioui.org/io/system"
    "gioui.org/layout"
    "gioui.org/op"
    "gioui.org/unit"
)

func main() {
    go func() {
            // create new window
            w := app.NewWindow(
                        app.Title("Egg timer"),
                        app.Size(unit.Dp(400), unit.Dp(600)),
            )

            // ops are the operations from the UI
            var ops op.Ops

            // listen for events in the window.
            for e := range w.Events() {

                        // detect what type of event
                        switch e := e.(type) {

                        // this is sent when the application should re-render.
                        case system.FrameEvent:
                                gtx := layout.NewContext(&ops, e)
                                e.Frame(gtx.Ops)
                        }
            }

            os.Exit(0)
    }()

    app.Main()
}
russoj88 commented 2 years ago

Looks like you're not actually running the code in this repo. The go.mod is different. If I use the go.mod you have, I get a panic as well.

Did you clone the repo, or did you write your own code?

rngoodner commented 2 years ago

I wrote from scratch while following along the tutorial. I guess the library has just changed in a breaking way since the tutorial was written. This should probably be expected until gio is 1.0. Maybe the version of gio the tutorial requires should be mentioned in the overview or chapter 1? I expect most people will follow along the tutorial and not just clone the pre-written code. It also does not seem practical to keep checking for breaking changes and updating the tutorial while gio is pre 1.0 as I suspect the core ideas will still transfer.

jonegil commented 2 years ago

Good comments and constructibe discussions, thanks all.

Yes, the os.Exit should probably be added to fully ensure expected behaviour across all systems.

And, yes, a version bump makes sense. It's not my expectation that you run older libs.

jonegil commented 2 years ago

I confirm I got the same and that it was more than a mere version bump. However, it was fairly straightforward as you pointed out. In the earliest chapters I've added an explicit

e.Frame()

along side the extra code needed by that e.Frame. Have a look now and see if it runs

jonegil commented 2 years ago

After conversing with Gio founder Elias yesterday, he identified it as an issue inside app/window.go. For such a simple application as the ones in chapter 1 and 2, where we don't even call e.Frame, this caused a panic.

This morning he patched Gio and fixed it so that an application does not panic when the client doesn't call FrameEvent.Frame:

bugfix The patch works on my local Gio, update yours and try.

That's quite a service from Elias, and kudos to @roborobs1023 and all in this thread for identifying and highlighting. Thanks!

roborobs1023 commented 2 years ago

Glad we were able to find it and kudos to Elias for being prompt in a resolution to such an issue.

Sent from Mailhttps://go.microsoft.com/fwlink/?LinkId=550986 for Windows

From: Jon Egil @.> Sent: Thursday, April 14, 2022 10:17 AM To: @.> Cc: Robert @.>; @.> Subject: Re: [jonegil/gui-with-gio] panic: runtime error: invalid memory address or nil pointer dereference (Issue #17)

After conversing with Gio founder Elias yesterday, he identified it as an issue inside app/window.go. For such a simple application as the ones in chapter 1 and 2, where we don't even call e.Frame, this caused a panic.

This morning he patched Gio and fixed it so that an application does not panic when the client doesn't call FrameEvent.Frame:

bugfixhttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.sr.ht%2F~eliasnaur%2Fgio%2Fcommit%2Fdc25afd&data=04%7C01%7C%7Ce905e5df366e4ac5371c08da1e2190d9%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637855426765933620%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=TDHHpb6%2FaZMVyGRfYF5S2QPLMN2xH7cZsshu5Ao6ht8%3D&reserved=0 The patch works on my local Gio, update yours and try.

That's quite a service from Elias, and kudos to @roborobs1023https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Froborobs1023&data=04%7C01%7C%7Ce905e5df366e4ac5371c08da1e2190d9%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637855426765933620%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=BrgHrgW9FcUtQtgdnM9V6x2o5gxmL%2B0wuNjhBfYVyqU%3D&reserved=0 and all in this thread for identifying and highlighting. Thanks!

— Reply to this email directly, view it on GitHubhttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fjonegil%2Fgui-with-gio%2Fissues%2F17%23issuecomment-1099234729&data=04%7C01%7C%7Ce905e5df366e4ac5371c08da1e2190d9%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637855426765933620%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=quj69nSlRboBPtq8Y%2FY9M1As45uyro6LWpt3NI4HBE4%3D&reserved=0, or unsubscribehttps://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAINFGXWLZWC2TNTJTOMUXBDVFASJDANCNFSM5ROXM33Q&data=04%7C01%7C%7Ce905e5df366e4ac5371c08da1e2190d9%7C84df9e7fe9f640afb435aaaaaaaaaaaa%7C1%7C0%7C637855426765933620%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&sdata=e5kxkAA6ClS9pIu5WWXjuQ%2F%2BJSN%2Bgy%2BAkaKzRJyqO80%3D&reserved=0. You are receiving this because you were mentioned.Message ID: @.***>