cogentcore / core

A free and open source framework for building powerful, fast, and elegant 2D and 3D apps that run on macOS, Windows, Linux, iOS, Android, and the Web with a single pure Go codebase, allowing you to Code Once, Run Everywhere.
http://cogentcore.org/core
BSD 3-Clause "New" or "Revised" License
1.32k stars 71 forks source link

fatal error: concurrent map writes #887

Closed ddkwork closed 4 months ago

ddkwork commented 4 months ago

Describe the bug

see title

How to reproduce

Sort by clicking on the header without crashing

Example code

package main

import (
    "cogentcore.org/core/events"
    "cogentcore.org/core/gi"
    "cogentcore.org/core/giv"
    "cogentcore.org/core/icons"
)

type TableStruct struct { //gti:add
    Icon       icons.Icon
    IntField   int `default:"2"`
    FloatField float32
    StrField   string
    File       gi.Filename
}

func main() {
    table := make([]*TableStruct, 0, 100000)
    b := gi.NewBody("leak")
    tv := giv.NewTableView(b, "tv")
    tv.SetReadOnly(true)
    tv.SetSlice(&table)

    b.OnShow(func(e events.Event) {
        go func() {
            for i := 0; i < 100000; i++ {
                table = append(table, &TableStruct{IntField: i, FloatField: float32(i) / 10.0})
                updt := tv.UpdateStartAsync()
                tv.UpdateWidgets()
                tv.UpdateEndAsyncRender(updt)
                if len(table) > 0 {
                    tv.ScrollToIdx(len(table) - 1)
                }
            }
        }()
    })

    b.RunMainWindow()
}

Relevant output

GOROOT=C:\Users\Admin\go\pkg\mod\golang.org\toolchain@v0.0.1-go1.22.0.windows-amd64 #gosetup
GOPATH=C:\Users\Admin\go #gosetup
C:\Users\Admin\go\pkg\mod\golang.org\toolchain@v0.0.1-go1.22.0.windows-amd64\bin\go.exe build -o C:\Users\Admin\AppData\Local\JetBrains\GoLand2023.3\tmp\GoLand\___1go_build_github_com_ddkwork_workspace_leak.exe github.com/ddkwork/workspace/leak #gosetup
C:\Users\Admin\AppData\Local\JetBrains\GoLand2023.3\tmp\GoLand\___1go_build_github_com_ddkwork_workspace_leak.exe
fatal error: concurrent map writes

goroutine 36 [running]:
cogentcore.org/core/ki.(*Node).SetProp(...)
        D:/workspace/workspace/core/ki/node.go:736
cogentcore.org/core/svg.(*SVG).UnmarshalXML(0xc0012aaea0, 0xc001357b00, {{{0xc0011716e0, 0x1a}, {0xc0013769bd, 0x3}}, {0xc001216f00, 0x4, 0x4}})
        D:/workspace/workspace/core/svg/io.go:179 +0x731e
cogentcore.org/core/svg.(*SVG).ReadXML(0xc0012aaea0, {0x7ff7545388c0?, 0xc0029bf260?})
        D:/workspace/workspace/core/svg/io.go:102 +0x15d
cogentcore.org/core/svg.(*SVG).OpenFS(0xc0012aaea0, {0x7ff754538be0?, 0xc000069f00?}, {0xc001376980?, 0xdb?})
        D:/workspace/workspace/core/svg/io.go:75 +0x22a
cogentcore.org/core/gi.(*Icon).SetIconTry(0xc0012aa608, {0x7ff7540fc7b2, 0x5})
        D:/workspace/workspace/core/gi/icon.go:84 +0x110
cogentcore.org/core/gi.(*Icon).SetIcon(0xc0012aa608, {0x7ff7540fc7b2, 0x5})
        D:/workspace/workspace/core/gi/icon.go:54 +0x37
cogentcore.org/core/gi.(*Button).ConfigWidget.func1()
        D:/workspace/workspace/core/gi/button.go:422 +0x8a
cogentcore.org/core/gi.(*WidgetBase).ConfigParts(0xc0012dd208, {0xc00028ded8, 0x1, 0x1}, {0xc000037d20, 0x1, 0xc000080808?})
        D:/workspace/workspace/core/gi/render.go:289 +0x6f
cogentcore.org/core/gi.(*Button).ConfigWidget(0xc0012dd208)
        D:/workspace/workspace/core/gi/button.go:419 +0x925
cogentcore.org/core/gi.(*Button).SetIconUpdate(0xc0012dd208, {0x7ff7540fc7b2, 0x5})
        D:/workspace/workspace/core/gi/button.go:272 +0x51
cogentcore.org/core/giv.(*IconValue).UpdateWidget(0xc0012b47e0)
        D:/workspace/workspace/core/giv/values.go:1358 +0x9d
cogentcore.org/core/giv.(*TableView).UpdateWidgets(0xc0003acc08)
        D:/workspace/workspace/core/giv/tableview.go:542 +0x9e9
main.main.func1()
        D:/workspace/workspace/leak/leak.go:28 +0x133
created by main.main in goroutine 1
        D:/workspace/workspace/leak/leak.go:24 +0x175

goroutine 1 [syscall, locked to thread]:
github.com/go-gl/glfw/v3.3/glfw._Cfunc_glfwWaitEvents()
        _cgo_gotypes.go:2494 +0x49
github.com/go-gl/glfw/v3.3/glfw.WaitEvents()
        C:/Users/Admin/go/pkg/mod/github.com/go-gl/glfw/v3.3/glfw@v0.0.0-20240118000515-a250818d05e3/window.go:949 +0x13
cogentcore.org/core/goosi/driver/desktop.(*App).MainLoop(0x7ff754c7bd00)
        D:/workspace/workspace/core/goosi/driver/desktop/app.go:73 +0x125
cogentcore.org/core/gi.Wait()
        D:/workspace/workspace/core/gi/renderwin.go:43 +0x4b
cogentcore.org/core/gi.(*Stage).Wait(...)
        D:/workspace/workspace/core/gi/stage.go:316
cogentcore.org/core/gi.(*Body).RunMainWindow(0xc0003acc08?)
        D:/workspace/workspace/core/gi/mainstage.go:38 +0x2b
main.main()
        D:/workspace/workspace/leak/leak.go:36 +0x17f

goroutine 81 [select]:
cogentcore.org/core/goosi/driver/base.(*Window[...]).WinLoop(0x7ff754542de0)
        D:/workspace/workspace/core/goosi/driver/base/window.go:93 +0x136
created by cogentcore.org/core/goosi/driver/desktop.(*App).NewWindow in goroutine 1
        D:/workspace/workspace/core/goosi/driver/desktop/app.go:171 +0xa66

goroutine 82 [sync.RWMutex.Lock]:
sync.runtime_SemacquireRWMutex(0x0?, 0x4?, 0x1?)
        C:/Users/Admin/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.windows-amd64/src/runtime/sema.go:87 +0x25
sync.(*RWMutex).Lock(0x1?)
        C:/Users/Admin/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.windows-amd64/src/sync/rwmutex.go:151 +0x6a
cogentcore.org/core/gi.(*RenderContext).WriteLock(...)
        D:/workspace/workspace/core/gi/renderwin.go:823
cogentcore.org/core/gi.(*RenderWin).RenderWindow(0xc00022c0f0)
        D:/workspace/workspace/core/gi/renderwin.go:982 +0x59
cogentcore.org/core/gi.(*RenderWin).HandleWindowEvents(0xc00022c0f0, {0x7ff754546ac8, 0xc000e8a1c0})
        D:/workspace/workspace/core/gi/renderwin.go:659 +0x565
cogentcore.org/core/gi.(*RenderWin).HandleEvent(0xc00022c0f0, {0x7ff754546ac8, 0xc000e8a1c0})
        D:/workspace/workspace/core/gi/renderwin.go:644 +0xe5
cogentcore.org/core/gi.(*RenderWin).EventLoop(0xc00022c0f0)
        D:/workspace/workspace/core/gi/renderwin.go:611 +0x125
created by cogentcore.org/core/gi.(*RenderWin).GoStartEventLoop in goroutine 1
        D:/workspace/workspace/core/gi/renderwin.go:565 +0xa5

goroutine 83 [semacquire]:
sync.runtime_Semacquire(0x0?)
        C:/Users/Admin/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.windows-amd64/src/runtime/sema.go:62 +0x25
sync.(*WaitGroup).Wait(0x0?)
        C:/Users/Admin/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.22.0.windows-amd64/src/sync/waitgroup.go:116 +0x48
cogentcore.org/core/gi.Wait.func2()
        D:/workspace/workspace/core/gi/renderwin.go:40 +0x37
created by cogentcore.org/core/gi.Wait in goroutine 1
        D:/workspace/workspace/core/gi/renderwin.go:38 +0x37

进程 已完成,退出代码为 2

Platform

Windows

ddkwork commented 4 months ago

Stable reproduction method: Click on a column other than the icon column and click the icon column again and again

kkoreilly commented 4 months ago

I will work on fixing this.

ddkwork commented 4 months ago

https://github.com/cogentcore/core/issues/851

ddkwork commented 4 months ago

I will work on fixing this.

After pulling the latest commit, panic: vulkan error: vulkan error: out of host memory (-1) It relapsed again, and another series of empty pointer nightmares Animation

ddkwork commented 4 months ago

I ended up refactoring a concurrency-safe version, the map issue seems to be solved, some demos of core are working fine, and some of the demos are still being changed

screenshots

ddkwork commented 4 months ago

see https://github.com/cogentcore/core/pull/891

Even if you don't plan to merge and change the PR, I still want you to pull my commit into a blank directory for testing, because after changing to a concurrent map, I find that the code is much simplified and more intuitive for me. It's really a one-and-done thing, although we can't get Rust-like security. Finally, I want to maintain this branch all the time, but I don't know if I can properly merge your subsequent commits to this branch when adding widgets and so on, and I hope to get your help.

kkoreilly commented 4 months ago

I apologize for the issues that I introduced in the recent commits to do with window closing, and I am working on fixing them now.

ddkwork commented 4 months ago

I apologize for the issues that I introduced in the recent commits to do with window closing, and I am working on fixing them now.

No need to apologize, you are too polite, I also want to apologize to you for my previous impulse, if you come to China, why don't you have a good meal and drink some wine, haha. Now all demos and apps except for the text editing widget are running normally, and I deleted part of the code in the ki attribute file, and I have to change it back later, because I tried about 7-8 times before to refactor it to change it, and found that there was no place to call it. I feel that the changes to the other parts are normal, because there is no code that breaks the drawing, thanks to your brilliant design: the drawings, behaviors, events, etc. of the interface are separate packages, and the design is good, I like your design idea.

ddkwork commented 4 months ago

Map substitution removes a myriad of type conversions in SVG and Ki packages.

kkoreilly commented 4 months ago

We completed an extensive redesign of our asynchronous updating process in the commits above, and all of the issues that you had with the nil panics and the map concurrency should be fixed now. Can you try examples/async in the latest version of the main branch and tell me if you have any issues?

ddkwork commented 4 months ago

We completed an extensive redesign of our asynchronous updating process in the commits above, and all of the issues that you had with the nil panics and the map concurrency should be fixed now. Can you try examples/async in the latest version of the main branch and tell me if you have any issues?

Thanks