lib/ui: fix GridCell.invalid race

This is read/written from different goroutines.

    Write at 0x00c00009c6f0 by goroutine 7:
      git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Grid).cellInvalidated()
          /home/simon/src/aerc2/lib/ui/grid.go:189 +0x122
      git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Grid).cellInvalidated-fm()
          /home/simon/src/aerc2/lib/ui/grid.go:178 +0x55
      git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate()
          /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85
      git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Bordered).contentInvalidated-fm()
          /home/simon/src/aerc2/lib/ui/borders.go:39 +0x56
      git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate()
          /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85
      git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList.func1()
          /home/simon/src/aerc2/widgets/dirlist.go:81 +0x55
      git.sr.ht/~sircmpwn/aerc2/lib/ui.(*Invalidatable).DoInvalidate()
          /home/simon/src/aerc2/lib/ui/invalidatable.go:22 +0x85
      git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start.func1()
          /home/simon/src/aerc2/widgets/spinner.go:88 +0x82

    Previous write at 0x00c00009c6f0 by main goroutine:
      [failed to restore the stack]

    Goroutine 7 (running) created at:
      git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start()
          /home/simon/src/aerc2/widgets/spinner.go:46 +0x98
      git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList()
          /home/simon/src/aerc2/widgets/dirlist.go:37 +0x28b
      git.sr.ht/~sircmpwn/aerc2/widgets.NewAccountView()
          /home/simon/src/aerc2/widgets/account.go:49 +0x5ca
      git.sr.ht/~sircmpwn/aerc2/widgets.NewAerc()
          /home/simon/src/aerc2/widgets/aerc.go:60 +0x807
      main.main()
          /home/simon/src/aerc2/aerc.go:65 +0x33e
This commit is contained in:
Simon Ser 2019-04-28 12:20:04 +00:00 committed by Drew DeVault
parent 5685a17674
commit 335db0402d

View file

@ -3,6 +3,7 @@ package ui
import ( import (
"fmt" "fmt"
"math" "math"
"sync/atomic"
) )
type Grid struct { type Grid struct {
@ -42,7 +43,7 @@ type GridCell struct {
RowSpan int RowSpan int
ColSpan int ColSpan int
Content Drawable Content Drawable
invalid bool invalid atomic.Value // bool
} }
func NewGrid() *Grid { func NewGrid() *Grid {
@ -85,7 +86,8 @@ func (grid *Grid) Draw(ctx *Context) {
grid.reflow(ctx) grid.reflow(ctx)
} }
for _, cell := range grid.cells { for _, cell := range grid.cells {
if !cell.invalid && !invalid { cellInvalid := cell.invalid.Load().(bool)
if !cellInvalid && !invalid {
continue continue
} }
rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan] rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan]
@ -156,11 +158,10 @@ func (grid *Grid) AddChild(content Drawable) *GridCell {
RowSpan: 1, RowSpan: 1,
ColSpan: 1, ColSpan: 1,
Content: content, Content: content,
invalid: true,
} }
grid.cells = append(grid.cells, cell) grid.cells = append(grid.cells, cell)
cell.Content.OnInvalidate(grid.cellInvalidated) cell.Content.OnInvalidate(grid.cellInvalidated)
cell.invalid = true cell.invalid.Store(true)
grid.invalidateLayout() grid.invalidateLayout()
return cell return cell
} }
@ -186,6 +187,6 @@ func (grid *Grid) cellInvalidated(drawable Drawable) {
if cell == nil { if cell == nil {
panic(fmt.Errorf("Attempted to invalidate unknown cell")) panic(fmt.Errorf("Attempted to invalidate unknown cell"))
} }
cell.invalid = true cell.invalid.Store(true)
grid.DoInvalidate(grid) grid.DoInvalidate(grid)
} }