awesome-gocui / gocui

Minimalist Go package aimed at creating Console User Interfaces.
BSD 3-Clause "New" or "Revised" License
350 stars 39 forks source link

[BUG] data race at each SetViewOnTop() #127

Open nomionz opened 1 year ago

nomionz commented 1 year ago

Describe the bug Every time program calls the SetViewOnTop() it will produce the data race.

To Reproduce Steps to reproduce the behavior:

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/awesome-gocui/gocui"
)

func main() {
    g, err := gocui.NewGui(gocui.OutputNormal, false)
    if err != nil {
        log.Panicln(err)
    }
    defer g.Close()

    g.SetManagerFunc(layout)

    if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil {
        log.Panicln(err)
    }

    if err := g.SetKeybinding("someview", gocui.KeyCtrlA, gocui.ModNone, onTop); err != nil {
        log.Panicln(err)
    }

    if err := g.SetKeybinding("someview2", gocui.KeyCtrlA, gocui.ModNone, onTop); err != nil {
        log.Panicln(err)
    }

    if err := g.MainLoop(); err != nil && err != gocui.ErrQuit {
        log.Panicln(err)
    }
}

func onTop(g *gocui.Gui, v *gocui.View) error {
    switch v.Name() {
    case "someview":
        g.SetViewOnTop("someview")
        g.SetCurrentView("someview2")
        g.SetViewOnBottom("someview2")
    case "someview2":
        g.SetViewOnTop("someview2")
        g.SetCurrentView("someview")
        g.SetViewOnBottom("someview")
    }
    return nil
}

func layout(g *gocui.Gui) error {
    maxX, maxY := g.Size()
    if v, err := g.SetView("someview", 0, 0, maxX, maxY-4, 0); err != nil {
        if err != gocui.ErrUnknownView {
            return err
        }
        v.Title = "someview"
        v.Editable = true
        g.SetCurrentView("someview")
        go dummy(g, v)
    }
    if v, err := g.SetView("someview2", maxX/2, 0, maxX-1, maxY-4, 0); err != nil {
        if err != gocui.ErrUnknownView {
            return err
        }
        v.Title = "someview2"
        v.Editable = true
        go dummy(g, v)

    }
    return nil
}

func dummy(g *gocui.Gui, v *gocui.View) {
    for {
        g.Update(func(g *gocui.Gui) error {
            for i := 0; i < 100; i++ {
                fmt.Fprintln(v, i)
            }
            return nil
        })
        time.Sleep(time.Second)
    }

}

func quit(g *gocui.Gui, v *gocui.View) error {
    return gocui.ErrQuit
}

Expected behavior No data race, because in original gocui there is no data race

Environment (please complete the following information):

Additional context data race stack trace

==================
WARNING: DATA RACE
Write at 0x00c000308040 by main goroutine:
  runtime.slicecopy()
      /usr/local/go/src/runtime/slice.go:310 +0x0
  github.com/awesome-gocui/gocui.(*Gui).SetViewOnTop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:244 +0xa93
  main.onTop()
      /home/nomionz/dev/test/main.go:40 +0xba2
  github.com/awesome-gocui/gocui.(*Gui).execKeybinding()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:947 +0x106
  github.com/awesome-gocui/gocui.(*Gui).execKeybindings()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:926 +0x37c
  github.com/awesome-gocui/gocui.(*Gui).onKey()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:882 +0x15d
  github.com/awesome-gocui/gocui.(*Gui).handleEvent()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:554 +0x5b
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:504 +0x3c4
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386

Previous read at 0x00c000308040 by goroutine 13:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick.func1()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:8 +0x139

Goroutine 13 (running) created at:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:6 +0x8e
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:477 +0x4a
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386
==================
==================
WARNING: DATA RACE
Write at 0x00c000308048 by main goroutine:
  github.com/awesome-gocui/gocui.(*Gui).SetViewOnTop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:245 +0xb04
  main.onTop()
      /home/nomionz/dev/test/main.go:40 +0xba2
  github.com/awesome-gocui/gocui.(*Gui).execKeybinding()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:947 +0x106
  github.com/awesome-gocui/gocui.(*Gui).execKeybindings()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:926 +0x37c
  github.com/awesome-gocui/gocui.(*Gui).onKey()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:882 +0x15d
  github.com/awesome-gocui/gocui.(*Gui).handleEvent()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:554 +0x5b
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:504 +0x3c4
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386

Previous read at 0x00c000308048 by goroutine 13:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick.func1()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:8 +0x139

Goroutine 13 (running) created at:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:6 +0x8e
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:477 +0x4a
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386
==================
==================
WARNING: DATA RACE
Write at 0x00c0002b4030 by main goroutine:
  runtime.slicecopy()
      /usr/local/go/src/runtime/slice.go:310 +0x0
  github.com/awesome-gocui/gocui.(*Gui).SetViewOnTop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:244 +0x30c
  main.onTop()
      /home/nomionz/dev/test/main.go:44 +0x41b
  github.com/awesome-gocui/gocui.(*Gui).execKeybinding()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:947 +0x106
  github.com/awesome-gocui/gocui.(*Gui).execKeybindings()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:926 +0x37c
  github.com/awesome-gocui/gocui.(*Gui).onKey()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:882 +0x15d
  github.com/awesome-gocui/gocui.(*Gui).handleEvent()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:554 +0x5b
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:504 +0x3c4
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386

Previous read at 0x00c0002b4030 by goroutine 13:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick.func1()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:8 +0x139

Goroutine 13 (running) created at:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:6 +0x8e
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:477 +0x4a
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386
==================
==================
WARNING: DATA RACE
Write at 0x00c0002b4038 by main goroutine:
  github.com/awesome-gocui/gocui.(*Gui).SetViewOnTop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:245 +0x37e
  main.onTop()
      /home/nomionz/dev/test/main.go:44 +0x41b
  github.com/awesome-gocui/gocui.(*Gui).execKeybinding()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:947 +0x106
  github.com/awesome-gocui/gocui.(*Gui).execKeybindings()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:926 +0x37c
  github.com/awesome-gocui/gocui.(*Gui).onKey()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:882 +0x15d
  github.com/awesome-gocui/gocui.(*Gui).handleEvent()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:554 +0x5b
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:504 +0x3c4
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386

Previous read at 0x00c0002b4038 by goroutine 13:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick.func1()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:8 +0x139

Goroutine 13 (running) created at:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:6 +0x8e
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:477 +0x4a
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386
==================
==================
WARNING: DATA RACE
Write at 0x00c0002ac010 by main goroutine:
  github.com/awesome-gocui/gocui.(*Gui).SetViewOnTop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:245 +0x3c4
  main.onTop()
      /home/nomionz/dev/test/main.go:44 +0x41b
  github.com/awesome-gocui/gocui.(*Gui).execKeybinding()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:947 +0x106
  github.com/awesome-gocui/gocui.(*Gui).execKeybindings()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:926 +0x37c
  github.com/awesome-gocui/gocui.(*Gui).onKey()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:882 +0x15d
  github.com/awesome-gocui/gocui.(*Gui).handleEvent()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:554 +0x5b
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:504 +0x3c4
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386

Previous read at 0x00c0002ac010 by goroutine 13:
  github.com/awesome-gocui/gocui.(*Gui).Views()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:266 +0x9b
  github.com/awesome-gocui/gocui.(*Gui).loaderTick.func1()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:8 +0xb5

Goroutine 13 (running) created at:
  github.com/awesome-gocui/gocui.(*Gui).loaderTick()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/loader.go:6 +0x8e
  github.com/awesome-gocui/gocui.(*Gui).MainLoop()
      /home/nomionz/go/pkg/mod/github.com/awesome-gocui/gocui@v1.1.0/gui.go:477 +0x4a
  main.main()
      /home/nomionz/dev/test/main.go:32 +0x386
==================
nomionz commented 1 year ago

For those wondering the workaround is to comment out the loaderTick() in the MainLoop() function. https://github.com/awesome-gocui/gocui/blob/384f06fbdddfe41d9ddebbcb58ccb67697246e8c/gui.go#L476-L477