gizak / termui

Golang terminal dashboard
MIT License
13.11k stars 786 forks source link

how to fix this data race? #172

Closed stephencheng closed 5 years ago

stephencheng commented 6 years ago

I have got the data race for this demo code, I am not sure what actually caused it and how I can fix it. Can someone point out, what is root cause? Is it from my code or this is some sort of known termui bug?

package main

import (
    "fmt"
    ui "github.com/gizak/termui"
    "github.com/gizak/termui/extra"
    "os"
)

func keyloopstatus() {

}

var keymap map[string]string = map[string]string{
    "c": "command mode",
}

var (
    keyin_started bool = false
    keyin_var     string
)

func handleAnyKey(e ui.Event) {
    key := e.Data.(ui.EvtKbd).KeyStr
    var action string

    if keyin_started {
        switch key {
        case "<enter>":
            action = fmt.Sprintf("entered, the whole input is: %s", keyin_var)
            keyin_started = false
            keyin_var = ""

        //case "<backspace>":
        case "C-8":
            if keylen := len(keyin_var); keylen > 0 {
                keyin_var = keyin_var[:(keylen - 1)]
            }

        default:
            keyin_var = keyin_var + key

        }

    } else {
        switch key {
        case "l":
            tabpane.SetActiveRight()
            ui.Clear()
            action = "tab right"

        case "h":
            tabpane.SetActiveLeft()
            ui.Clear()
            action = "tab left"
        case "s":
            ui.Clear()
            keyin_started = true
            action = "switch code, please input the code:"
        }
    }

    msg := fmt.Sprintf("key: %s -> %s ", key, action)
    input := fmt.Sprintf("input: %s", keyin_var)
    ui.SendCustomEvt("/usr/header", input)
    ui.SendCustomEvt("/usr/keyindicator", msg)
}

func registerEventHandlers() {
    ui.Handle("/sys/kbd/", func(ev ui.Event) {
        handleAnyKey(ev)
    })
    ui.Handle("/sys/kbd/C-c", func(ui.Event) {
        handleQuit()
    })
    ui.Handle("/sys/wnd/resize", func(ui.Event) {
        handleResize()
    })
    ui.Handle("/usr/keyindicator", func(e ui.Event) {
        keyindicator.Text = e.Data.(string)
        ui.Clear()
        ui.Render(header, keyindicator, tabpane)
    })
    ui.Handle("/usr/header", func(e ui.Event) {
        header.Text = e.Data.(string)
        ui.Clear()
        ui.Render(header, keyindicator, tabpane)
    })

}

func handleQuit() {
    ui.Close()
    os.Exit(0)
}

func handleResize() {

}

var keyindicator, header, header3 *ui.Par
var tabpane *extra.Tabpane

func main() {
    err := ui.Init()
    if err != nil {
        panic(err)
    }
    defer ui.Close()

    header = ui.NewPar("[Press q to quit, Press h or l to switch tabs]")
    header.Height = 1
    header.Width = 300
    header.Border = false
    header.TextBgColor = ui.ColorBlue

    keyindicator = ui.NewPar("[command bar]")
    keyindicator.Height = 1
    keyindicator.Width = 100
    keyindicator.X = 50
    keyindicator.Border = false
    keyindicator.TextBgColor = ui.ColorGreen

    header3 = ui.NewPar("[command input bar]")
    header3.Height = 1
    header3.Width = 100
    header3.X = 150
    header3.Border = false
    header3.TextBgColor = ui.ColorGreen

    tab1 := extra.NewTab("market")
    par2 := ui.NewPar("par2\n")
    par2.Height = 5
    par2.Width = 100
    par2.Y = 0
    par2.BorderLabel = "Keys"
    par2.BorderFg = ui.ColorYellow
    tab1.AddBlocks(par2)

    tab2 := extra.NewTab("drugi")
    bc := ui.NewBarChart()
    data := []int{3, 2, 5, 3, 9, 5, 3, 2, 5, 8, 3, 2, 4, 5, 3, 2, 5, 7, 5, 3, 2, 6, 7, 4, 6, 3, 6, 7, 8, 3, 6, 4, 5, 3, 2, 4, 6, 4, 8, 5, 9, 4, 3, 6, 5, 3, 6}
    bclabels := []string{"S0", "S1", "S2", "S3", "S4", "S5"}
    bc.BorderLabel = "Bar Chart"
    bc.Data = data
    bc.Width = 26
    bc.Height = 10
    bc.DataLabels = bclabels
    bc.TextColor = ui.ColorGreen
    bc.BarColor = ui.ColorRed
    bc.NumColor = ui.ColorYellow
    tab2.AddBlocks(bc)

    tab3 := extra.NewTab("trzeci")

    tabpane = extra.NewTabpane()
    tabpane.Y = 1
    tabpane.Width = 230
    tabpane.Border = true

    tabpane.SetTabs(*tab1, *tab2, *tab3)

    ui.Render(header, keyindicator, tabpane)

    registerEventHandlers()

    ui.Loop()
}

the error:

==================
WARNING: DATA RACE
Write at 0x00c42009c560 by goroutine 25:
  os.(*file).close()
      /usr/local/Cellar/go/1.8/libexec/src/os/file_unix.go:143 +0x10a
  os.(*File).Close()
      /usr/local/Cellar/go/1.8/libexec/src/os/file_unix.go:132 +0x55
  github.com/gizak/termui/vendor/github.com/nsf/termbox-go.Close()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/vendor/github.com/nsf/termbox-go/api.go:130 +0x400
  github.com/gizak/termui.Close()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/render.go:75 +0x2f
  main.handleQuit()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:93 +0x2f
  main.registerEventHandlers.func2()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:74 +0x2f
  github.com/gizak/termui.(*EvtStream).Loop.func1()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:251 +0x162

Previous read at 0x00c42009c560 by goroutine 22:
  [failed to restore the stack]

Goroutine 25 (running) created at:
  github.com/gizak/termui.(*EvtStream).Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:253 +0x192
  github.com/gizak/termui.Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:278 +0x4a
  main.main()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:167 +0xc3f

Goroutine 22 (running) created at:
  github.com/gizak/termui.(*EvtStream).Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:253 +0x192
  github.com/gizak/termui.Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:278 +0x4a
  main.main()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:167 +0xc3f
==================
==================
WARNING: DATA RACE
Write at 0x000001295458 by goroutine 25:
  github.com/gizak/termui/vendor/github.com/nsf/termbox-go.Close()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/vendor/github.com/nsf/termbox-go/api.go:134 +0x433
  github.com/gizak/termui.Close()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/render.go:75 +0x2f
  main.handleQuit()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:93 +0x2f
  main.registerEventHandlers.func2()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:74 +0x2f
  github.com/gizak/termui.(*EvtStream).Loop.func1()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:251 +0x162

Previous read at 0x000001295458 by goroutine 22:
  [failed to restore the stack]

Goroutine 25 (running) created at:
  github.com/gizak/termui.(*EvtStream).Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:253 +0x192
  github.com/gizak/termui.Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:278 +0x4a
  main.main()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:167 +0xc3f

Goroutine 22 (running) created at:
  github.com/gizak/termui.(*EvtStream).Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:253 +0x192
  github.com/gizak/termui.Loop()
      /Users/stephencheng/data/workspace/golangworkspace/personal/src/github.com/gizak/termui/events.go:278 +0x4a
  main.main()
      /Users/stephencheng/data/workspace/golangworkspace/gocmartoo/src/gitlab.com/cmartoo/gocmartoo/examples/termui/race/errored/main.go:167 +0xc3f
==================
cjbassi commented 5 years ago

So I'm pretty sure this was just a termui bug. Some other people were reporting data races too but termui has recently been heavily rewritten and the data races should be fixed. Do note that there have been a lot of breaking changes if/when you decide to upgrade.