summary refs log tree commit diff stats
path: root/lib/ui/grid.go
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2019-04-28 12:20:04 +0000
committerDrew DeVault <sir@cmpwn.com>2019-04-29 09:29:37 -0400
commit335db0402decf1e0a3b07e7c51ab62a4f6baab50 (patch)
treed6d4b96fc027b9a7d98d9a66817bf9a5a8152a55 /lib/ui/grid.go
parent5685a176747711d0330f1251ad297b13e0621a37 (diff)
downloadaerc-335db0402decf1e0a3b07e7c51ab62a4f6baab50.tar.gz
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
Diffstat (limited to 'lib/ui/grid.go')
-rw-r--r--lib/ui/grid.go11
1 files changed, 6 insertions, 5 deletions
diff --git a/lib/ui/grid.go b/lib/ui/grid.go
index 3ac43a4..3fc7f04 100644
--- a/lib/ui/grid.go
+++ b/lib/ui/grid.go
@@ -3,6 +3,7 @@ package ui
 import (
 	"fmt"
 	"math"
+	"sync/atomic"
 )
 
 type Grid struct {
@@ -42,7 +43,7 @@ type GridCell struct {
 	RowSpan int
 	ColSpan int
 	Content Drawable
-	invalid bool
+	invalid atomic.Value // bool
 }
 
 func NewGrid() *Grid {
@@ -85,7 +86,8 @@ func (grid *Grid) Draw(ctx *Context) {
 		grid.reflow(ctx)
 	}
 	for _, cell := range grid.cells {
-		if !cell.invalid && !invalid {
+		cellInvalid := cell.invalid.Load().(bool)
+		if !cellInvalid && !invalid {
 			continue
 		}
 		rows := grid.rowLayout[cell.Row : cell.Row+cell.RowSpan]
@@ -156,11 +158,10 @@ func (grid *Grid) AddChild(content Drawable) *GridCell {
 		RowSpan: 1,
 		ColSpan: 1,
 		Content: content,
-		invalid: true,
 	}
 	grid.cells = append(grid.cells, cell)
 	cell.Content.OnInvalidate(grid.cellInvalidated)
-	cell.invalid = true
+	cell.invalid.Store(true)
 	grid.invalidateLayout()
 	return cell
 }
@@ -186,6 +187,6 @@ func (grid *Grid) cellInvalidated(drawable Drawable) {
 	if cell == nil {
 		panic(fmt.Errorf("Attempted to invalidate unknown cell"))
 	}
-	cell.invalid = true
+	cell.invalid.Store(true)
 	grid.DoInvalidate(grid)
 }