Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[bug] SIGSEGV: Segment Violation with Progress Bar #819

Closed
xEricL opened this issue Jul 9, 2024 · 17 comments · Fixed by #872
Closed

[bug] SIGSEGV: Segment Violation with Progress Bar #819

xEricL opened this issue Jul 9, 2024 · 17 comments · Fixed by #872
Assignees
Labels
bug Something isn't working

Comments

@xEricL
Copy link

xEricL commented Jul 9, 2024

What happend?

This code worked in v0.7. Updating to v0.8.1 causes a segment violation at runtime.

SIGSEGV: segmentation violation
PC=0x7fdd72531b29 m=13 sigcode=1 addr=0x998
signal arrived during cgo execution

goroutine 5 gp=0xc000007c00 m=13 mp=0xc000501808 [syscall]:
runtime.cgocall(0x74a7e0, 0xc000070590)
        runtime/cgocall.go:157 +0x4b fp=0xc000070568 sp=0xc000070530 pc=0x40ed0b
github.com/AllenDang/cimgui-go._Cfunc_igDeleteTexture(0x25)
        _cgo_gotypes.go:23190 +0x3f fp=0xc000070590 sp=0xc000070568 pc=0x6eb8ff
github.com/AllenDang/cimgui-go.(*GLFWBackend).DeleteTexture.func1({0x7fdd71a9c548?})
        github.com/AllenDang/[email protected]/glfw_backend.go:376 +0x34 fp=0xc0000705c8 sp=0xc000070590 pc=0x6f2bf4
github.com/AllenDang/cimgui-go.(*GLFWBackend).DeleteTexture(0x10?, {0xc000501808?})
        github.com/AllenDang/[email protected]/glfw_backend.go:376 +0x16 fp=0xc0000705e0 sp=0xc0000705c8 pc=0x6f2b96
github.com/AllenDang/cimgui-go.(*Texture).release(0x0?)
        github.com/AllenDang/[email protected]/texture.go:36 +0x28 fp=0xc000070600 sp=0xc0000705e0 pc=0x6eac28
runtime.call16(0x0, 0xe17808, 0xc000124010, 0x10, 0x10, 0x10, 0xc000070690)
        runtime/asm_amd64.s:770 +0x43 fp=0xc000070620 sp=0xc000070600 pc=0x4755a3
runtime.runfinq()
        runtime/mfinal.go:256 +0x3f1 fp=0xc0000707e0 sp=0xc000070620 pc=0x424331
runtime.goexit({})
        runtime/asm_amd64.s:1695 +0x1 fp=0xc0000707e8 sp=0xc0000707e0 pc=0x477061
created by runtime.createfing in goroutine 1
        runtime/mfinal.go:164 +0x3d

goroutine 1 gp=0xc0000061c0 m=nil [select, locked to thread]:
runtime.gopark(0xc000551e50?, 0x2?, 0xb8?, 0x9?, 0xc000551e44?)
        runtime/proc.go:402 +0xce fp=0xc000551cf0 sp=0xc000551cd0 pc=0x4450ce
runtime.selectgo(0xc000551e50, 0xc000551e40, 0x18?, 0x0, 0xc000384030?, 0x1)
        runtime/select.go:327 +0x725 fp=0xc000551e10 sp=0xc000551cf0 pc=0x456705
github.com/faiface/mainthread.Run(0xc000384030)
        github.com/faiface/[email protected]/mainthread.go:42 +0x10d fp=0xc000551e88 sp=0xc000551e10 pc=0x6ff5ad
github.com/AllenDang/giu.mainthreadCallPlatform(...)
        github.com/AllenDang/[email protected]/mainthread_all.go:9
github.com/AllenDang/giu.(*MasterWindow).Run(...)
        github.com/AllenDang/[email protected]/MasterWindow.go:236
github.com/alpine-client/pinnacle/ui.Render()
        github.com/alpine-client/pinnacle/ui/ui.go:112 +0x67 fp=0xc000551eb0 sp=0xc000551e88 pc=0x707d67
main.Run()
        github.com/alpine-client/pinnacle/main.go:50 +0xf0 fp=0xc000551f10 sp=0xc000551eb0 pc=0x7120b0
main.main()
        github.com/alpine-client/pinnacle/main.go:28 +0xb2 fp=0xc000551f50 sp=0xc000551f10 pc=0x711f92
runtime.main()
        runtime/proc.go:271 +0x29d fp=0xc000551fe0 sp=0xc000551f50 pc=0x444c9d
runtime.goexit({})
        runtime/asm_amd64.s:1695 +0x1 fp=0xc000551fe8 sp=0xc000551fe0 pc=0x477061

goroutine 2 gp=0xc000006c40 m=nil [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        runtime/proc.go:402 +0xce fp=0xc000070fa8 sp=0xc000070f88 pc=0x4450ce
runtime.goparkunlock(...)
        runtime/proc.go:408
runtime.forcegchelper()
        runtime/proc.go:326 +0xb3 fp=0xc000070fe0 sp=0xc000070fa8 pc=0x444f53
runtime.goexit({})
        runtime/asm_amd64.s:1695 +0x1 fp=0xc000070fe8 sp=0xc000070fe0 pc=0x477061
created by runtime.init.6 in goroutine 1
        runtime/proc.go:314 +0x1a

goroutine 3 gp=0xc000007180 m=nil [runnable]:
runtime.goschedIfBusy()
        runtime/proc.go:365 +0x28 fp=0xc000071780 sp=0xc000071768 pc=0x444fe8
runtime.bgsweep(0xc00009a000)
        runtime/mgcsweep.go:302 +0x14f fp=0xc0000717c8 sp=0xc000071780 pc=0x43076f
runtime.gcenable.gowrap1()
        runtime/mgc.go:203 +0x25 fp=0xc0000717e0 sp=0xc0000717c8 pc=0x425005
runtime.goexit({})
        runtime/asm_amd64.s:1695 +0x1 fp=0xc0000717e8 sp=0xc0000717e0 pc=0x477061
created by runtime.gcenable in goroutine 1
        runtime/mgc.go:203 +0x66

Code example

main.go
//go:embed assets/*
var assets embed.FS
var (
	logo *image.RGBA
	window *giu.MasterWindow
)

func main(){
	window = giu.NewMasterWindow(
		"Updater",
		377, 144,
		giu.MasterWindowFlagsFrameless|giu.MasterWindowFlagsNotResizable|giu.MasterWindowFlagsTransparent,
	)
        logo, _ = loadImage(assets, "assets/logo.png")
	window.Run(defaultUI)
}

func defaultUI() {
	giu.SingleWindow().Layout(
		giu.Align(giu.AlignCenter).To(
			giu.Dummy(0, scaleDivider(6)),
			giu.ImageWithRgba(logo).Size(80, 80),
			giu.Dummy(0, scaleDivider(6)),
			giu.ProgressBar(ReadProgress()).Size(scaleValueX(377)*0.75, scaleValueY(5)),
		),
	)
}

func scaleDivider(value float32) float32 {
	_, yScale := giu.Context.Backend().ContentScale()
	if yScale > 1.0 {
		value *= 2
	}
	return value * yScale
}

func scaleValueY(value int) float32 {
	_, yScale := giu.Context.Backend().ContentScale()
	return float32(value) * yScale
}

func scaleValueX(value int) float32 {
	xScale, _ := giu.Context.Backend().ContentScale()
	return float32(value) * xScale
}

func loadImage(assets embed.FS, path string) (*image.RGBA, error) {
	data, err := assets.ReadFile(path)
	if err != nil {
		return nil, err
	}

	img, err := png.Decode(bytes.NewReader(data))
	if err != nil {
		return nil, err
	}

	return giu.ImageToRgba(img), nil
}

You can also find the actual code I'm using this for here: https://github.com/alpine-client/pinnacle/blob/084fde184a816b2241c36bd4f37a9fced3f21dbf/ui/ui.go#L83

To Reproduce

  1. Run my demo
  2. will see the crash...

Version

(latest)

OS

Fedora 40

@xEricL xEricL added the bug Something isn't working label Jul 9, 2024
@gucio321
Copy link
Collaborator

@xEricL, I can't reproduce

Here is the code I'm using

package main

import (
	"bytes"
	"embed"
	"image"
	"image/png"

	"github.com/AllenDang/giu"
)

//go:embed assets/*
var assets embed.FS

var (
	logo   *image.RGBA
	window *giu.MasterWindow
)

func main() {
	window = giu.NewMasterWindow(
		"Updater",
		377, 144,
		giu.MasterWindowFlagsFrameless|giu.MasterWindowFlagsNotResizable|giu.MasterWindowFlagsTransparent,
	)
	logo, _ = loadImage(assets, "assets/logo.png")
	window.Run(defaultUI)
}

func defaultUI() {
	giu.SingleWindow().Layout(
		giu.Align(giu.AlignCenter).To(
			giu.Dummy(0, scaleDivider(6)),
			giu.ImageWithRgba(logo).Size(80, 80),
			giu.Dummy(0, scaleDivider(6)),
			giu.ProgressBar(ReadProgress()).Size(scaleValueX(377)*0.75, scaleValueY(5)),
		),
	)
}

func ReadProgress() float32 {
	return 0.5
}

func scaleDivider(value float32) float32 {
	_, yScale := giu.Context.Backend().ContentScale()
	if yScale > 1.0 {
		value *= 2
	}
	return value * yScale
}

func scaleValueY(value int) float32 {
	_, yScale := giu.Context.Backend().ContentScale()
	return float32(value) * yScale
}

func scaleValueX(value int) float32 {
	xScale, _ := giu.Context.Backend().ContentScale()
	return float32(value) * xScale
}

func loadImage(assets embed.FS, path string) (*image.RGBA, error) {
	data, err := assets.ReadFile(path)
	if err != nil {
		return nil, err
	}

	img, err := png.Decode(bytes.NewReader(data))
	if err != nil {
		return nil, err
	}

	return giu.ImageToRgba(img), nil
}

It works fine (assets/logo.png for me is examples/loadimage/gopher.png)

I've a suggestion for your project: make sure your style.go does not use AllenDang/imgui-go - you need AllenDang/cimgui-go

@xEricL
Copy link
Author

xEricL commented Jul 20, 2024

I've a suggestion for your project: make sure your style.go does not use AllenDang/imgui-go - you need AllenDang/cimgui-go

@gucio321 I've made sure to update my style.go. I've pushed the updated code to a new branch https://github.com/alpine-client/pinnacle/tree/giu-v0.8

I didn't think styling was the issue because it still happens even if I removed SetupStyle and PopStyle from the defaultUI() function.

After further testing, I've discovered 2 cases where the SIGSEV does not happen (which should narrow down the issue):

  1. Removing giu.ImageWithRgba(logo) from defaultUI(). Specifically, this line: https://github.com/alpine-client/pinnacle/blob/92462557244d9d37c35cae535529d894a9e5b21d/ui/ui.go#L88
  2. Do 1 successful run (case 1), but then add back the giu.ImageWithRgba(logo) line and run the code again (skips most of the progress bar)

Let me further explain our program. It basically downloads and unzips Java 17, downloads a launcher.jar from our website, and then uses the Java binary to run launcher.jar. This only needs to happen once, so if the program detects that the Java runtime package and launcher.jar already exist on the system, it doesn't do it again. This means the progress bar goes much faster after 1 successful run. As a result, if you get the program to run successfully, you need to delete ~/.alpineclient/ before running it again or else SIGSEV won't happen again (I know, it's very strange).

Since you're unable to recreate it, please clone this branch, run make run, and the SIGSEV should happen. Once again, the program only interacts with ~/.alpineclient/, so remember to delete that after a successful run (and at the end when you're finished testing). I've also commented out the code that runs launcher.jar (so no other code will be executed on your system).

Please let me know if you're still unable to recreate it under these conditions. The issue is most likely related to giu.ImageWithRgba (case 1). Although I don't know why the SIGSEV doesn't happen after 1 successful run (case 2).

@xEricL
Copy link
Author

xEricL commented Jul 21, 2024

Even if I comment out the progress bar and only load the image by itself, the SIGSEV occurs. It is almost certainly caused by giu.ImageWithRgba.

@xEricL
Copy link
Author

xEricL commented Jul 21, 2024

Replacing giu.ImageWithRgba with giu.ImageWithURL fixes the issue. Not an ideal solution but will have to do in the meantime. This is probably a lower-level issue with cimgui-go.

@gucio321
Copy link
Collaborator

Image with url is almost the same as image with rgba iirc
So this night be a giu issue, let me investigate it

@gucio321 gucio321 self-assigned this Jul 22, 2024
@gucio321
Copy link
Collaborator

@xEricL I'm sorry but I'm still unable to reproduce:

giudebug2.mp4

@xEricL
Copy link
Author

xEricL commented Jul 22, 2024

That is very interesting. I just tested it in a Debian 11 Virtual Machine and it compiled and ran no problem. Perhaps it's just an issue with Fedora 40 or maybe even just a problem with my system.

Thank you for the video and for taking the time to look into this.

@gucio321
Copy link
Collaborator

@xEricL I'm on fedora 39. I can check on f40 laptop later.

You use wayland or xorg? And what gpu?

@xEricL
Copy link
Author

xEricL commented Jul 23, 2024

You use wayland or xorg? And what gpu?

I'm on xorg. GPU is NVIDIA 2060S.

@gucio321
Copy link
Collaborator

@xEricL I managed to reproduce on fedora 40 laptop with nvidia gpu.
I have no idea is it hardware or os thing yet.
Will try to debug this.

@gucio321
Copy link
Collaborator

fedora 40 PC with no gpu - still works for me. This must be something about gpu (but why?)
Generally ImageWithRGBa has something to do with texture loading and this is deffinitly gpu thing.

@xEricL
Copy link
Author

xEricL commented Jul 23, 2024

It likely has something to do with NVIDIA drivers for Fedora 40.

Very weird that giu.ImageWithURL and giu.ImageWithFile work just fine. I decided to just go with giu.ImageWithFile. Perhaps it will resolve on it's own with a NVIDIA driver update in the future. Thank you again for taking the time to look into this for me.

@terranvigil
Copy link

terranvigil commented Aug 23, 2024

Same issue here. Fixed by switching from ImageWithRgbaWidget to ImageWithFileWidget. Apple M1 Pro.

SIGSEGV: segmentation violation
PC=0x1d73748f8 m=9 sigcode=2 addr=0x30
signal arrived during cgo execution

goroutine 3 gp=0x14000003880 m=9 mp=0x1400007e808 [syscall]:
runtime.cgocall(0x104f7affc, 0x140000504e8)
	/usr/local/go/src/runtime/cgocall.go:167 +0x44 fp=0x140000504b0 sp=0x14000050470 pc=0x104bddf24
github.com/AllenDang/cimgui-go._Cfunc_igDeleteTexture(0x6)
	_cgo_gotypes.go:23020 +0x30 fp=0x140000504e0 sp=0x140000504b0 pc=0x104d24050
github.com/AllenDang/cimgui-go.(*GLFWBackend).DeleteTexture.func1({0x14000050548?})

@gucio321
Copy link
Collaborator

@terranvigil what gpu?

@terranvigil
Copy link

@terranvigil what gpu?

It's the integrated Apple GPU, 16 core

@gucio321
Copy link
Collaborator

I had a chat on discord with someone who has similar issue. Turns out it happens independently to ProgressBar.
If you just use ImageWithRgba to display an image and wait about 30 seconds it will crash with no reason.

code
package main

import (
    "fmt"
    "image"

    g "github.com/AllenDang/giu"
)

var (
    rgba *image.RGBA
)

func loop() {
    g.SingleWindow().Layout(
        g.Label("Display image from rgba"),
        g.ImageWithRgba(rgba).OnClick(func() {
            fmt.Println("rgba image was clicked")
        }).Size(200, 100),

    )
}

func main() {
    rgba, _ = g.LoadImage("./fallback.png")

    wnd := g.NewMasterWindow("Load Image", 600, 500, 0)
    wnd.Run(loop)
}

@terranvigil could you confirm?

@cjbrigato
Copy link
Contributor

I proposed a simple solution to the imageWithRgba issue there, that work flawlessy for me. Gone from 2gb gpu vram (or crash) down to 60Mb

#854 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants