diff options
author | Simon Ser <contact@emersion.fr> | 2019-05-19 11:40:05 +0000 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2019-05-19 11:37:38 -0400 |
commit | 1da3239345ec64a1246538a8b5e37d544b244cba (patch) | |
tree | 5fb217b32fe5580bcb0fdf0f03158e90ee83e80f | |
parent | ca2cd00fe75863002145afcbfad1fe03f6258cfc (diff) |
widgets/terminal: fix damage race condition
Terminal.damage is accessed when drawing and when invalidating the widget. For
this reason we need to protect it with a mutex.
This seems to fix various damage issues I've been experiencing (where some
regions of the terminal weren't correctly repainted).
Race detector trace:
Read at 0x00c0000c6670 by main goroutine:
git.sr.ht/~sircmpwn/aerc/widgets.(*Terminal).Draw()
/home/simon/src/aerc/widgets/terminal.go:292 +0x191
git.sr.ht/~sircmpwn/aerc/lib/ui.(*Grid).Draw()
/home/simon/src/aerc/lib/ui/grid.go:117 +0x575
git.sr.ht/~sircmpwn/aerc/lib/ui.(*Grid).Draw()
/home/simon/src/aerc/lib/ui/grid.go:117 +0x575
git.sr.ht/~sircmpwn/aerc/widgets.(*MessageViewer).Draw()
/home/simon/src/aerc/widgets/msgviewer.go:231 +0x253
git.sr.ht/~sircmpwn/aerc/lib/ui.(*TabContent).Draw()
/home/simon/src/aerc/lib/ui/tab.go:124 +0x12e
git.sr.ht/~sircmpwn/aerc/lib/ui.(*Grid).Draw()
/home/simon/src/aerc/lib/ui/grid.go:117 +0x575
git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Draw()
/home/simon/src/aerc/widgets/aerc.go:95 +0x5a
git.sr.ht/~sircmpwn/aerc/lib/ui.(*UI).Tick()
/home/simon/src/aerc/lib/ui/ui.go:93 +0x1dd
main.main()
/home/simon/src/aerc/aerc.go:105 +0x539
Previous write at 0x00c0000c6670 by goroutine 37:
git.sr.ht/~sircmpwn/aerc/widgets.(*Terminal).onDamage-fm()
/home/simon/src/aerc/widgets/terminal.go:429 +0x131
git.sr.ht/~sircmpwn/go-libvterm._go_handle_damage()
/home/simon/go/pkg/mod/git.sr.ht/~sircmpwn/go-libvterm@v0.0.0-20190421201021-3184f6f13687/vterm.go:481 +0xf9
git.sr.ht/~sircmpwn/go-libvterm._cgoexpwrap_5e22200b58b7__go_handle_damage()
_cgo_gotypes.go:731 +0x58
runtime.call32()
/usr/lib/go/src/runtime/asm_amd64.s:519 +0x3a
git.sr.ht/~sircmpwn/go-libvterm.(*VTerm).Write.func1()
/home/simon/go/pkg/mod/git.sr.ht/~sircmpwn/go-libvterm@v0.0.0-20190421201021-3184f6f13687/vterm.go:329 +0x9d
git.sr.ht/~sircmpwn/go-libvterm.(*VTerm).Write()
/home/simon/go/pkg/mod/git.sr.ht/~sircmpwn/go-libvterm@v0.0.0-20190421201021-3184f6f13687/vterm.go:329 +0x7f
git.sr.ht/~sircmpwn/aerc/widgets.NewTerminal.func1()
/home/simon/src/aerc/widgets/terminal.go:131 +0x18c
Goroutine 37 (running) created at:
git.sr.ht/~sircmpwn/aerc/widgets.NewTerminal()
/home/simon/src/aerc/widgets/terminal.go:121 +0x23f
git.sr.ht/~sircmpwn/aerc/widgets.NewMessageViewer()
/home/simon/src/aerc/widgets/msgviewer.go:147 +0xfbe
git.sr.ht/~sircmpwn/aerc/commands/account.ViewMessage()
/home/simon/src/aerc/commands/account/view-message.go:26 +0x4a4
git.sr.ht/~sircmpwn/aerc/commands.(*Commands).ExecuteCommand()
/home/simon/src/aerc/commands/commands.go:47 +0x1f0
main.main.func1()
/home/simon/src/aerc/aerc.go:76 +0x205
git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).BeginExCommand.func1()
/home/simon/src/aerc/widgets/aerc.go:262 +0x89
git.sr.ht/~sircmpwn/aerc/widgets.(*ExLine).Event()
/home/simon/src/aerc/widgets/exline.go:47 +0x222
git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Event()
/home/simon/src/aerc/widgets/aerc.go:133 +0x83c
git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).simulate()
/home/simon/src/aerc/widgets/aerc.go:126 +0x12a
git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Event()
/home/simon/src/aerc/widgets/aerc.go:148 +0x766
git.sr.ht/~sircmpwn/aerc/lib/ui.(*UI).Tick()
/home/simon/src/aerc/lib/ui/ui.go:86 +0x11b
main.main()
/home/simon/src/aerc/aerc.go:105 +0x539
-rw-r--r-- | widgets/terminal.go | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/widgets/terminal.go b/widgets/terminal.go index a3615a5..99e99ae 100644 --- a/widgets/terminal.go +++ b/widgets/terminal.go @@ -4,6 +4,7 @@ import ( gocolor "image/color" "os" "os/exec" + "sync" "git.sr.ht/~sircmpwn/aerc/lib/ui" @@ -95,7 +96,6 @@ type Terminal struct { ctx *ui.Context cursorPos vterm.Pos cursorShown bool - damage []vterm.Rect destroyed bool err error focus bool @@ -103,6 +103,9 @@ type Terminal struct { start chan interface{} vterm *vterm.VTerm + damage []vterm.Rect // protected by mutex + mutex sync.Mutex + OnClose func(err error) OnEvent func(event tcell.Event) bool OnStart func() @@ -230,7 +233,9 @@ func (term *Terminal) Invalidate() { if term.vterm != nil { width, height := term.vterm.Size() rect := vterm.NewRect(0, width, 0, height) + term.mutex.Lock() term.damage = append(term.damage, *rect) + term.mutex.Unlock() } term.invalidate() } @@ -274,7 +279,9 @@ func (term *Terminal) Draw(ctx *ui.Context) { pty.Setsize(term.pty, &winsize) term.vterm.SetSize(ctx.Height(), ctx.Width()) rect := vterm.NewRect(0, ctx.Width(), 0, ctx.Height()) + term.mutex.Lock() term.damage = append(term.damage, *rect) + term.mutex.Unlock() return } } @@ -289,6 +296,7 @@ func (term *Terminal) Draw(ctx *ui.Context) { // naive optimization visited := make(map[coords]interface{}) + term.mutex.Lock() for _, rect := range term.damage { for x := rect.StartCol(); x < rect.EndCol() && x < ctx.Width(); x += 1 { @@ -311,6 +319,7 @@ func (term *Terminal) Draw(ctx *ui.Context) { } term.damage = nil + term.mutex.Unlock() if term.focus && !term.closed { if !term.cursorShown { @@ -426,7 +435,9 @@ func (term *Terminal) styleFromCell(cell *vterm.ScreenCell) tcell.Style { } func (term *Terminal) onDamage(rect *vterm.Rect) int { + term.mutex.Lock() term.damage = append(term.damage, *rect) + term.mutex.Unlock() term.invalidate() return 1 } |