widgets/terminal: Don't segfault on resize

vterm.Write and vterm.SetSize race when the window resizes, which
causing the underlying library to segfault.

Signed-off-by: Kevin Kuehler <keur@ocf.berkeley.edu>
This commit is contained in:
Kevin Kuehler 2019-05-25 02:06:15 -07:00 committed by Drew DeVault
parent 0bfb90baed
commit 3445b80d7a
1 changed files with 15 additions and 10 deletions

View File

@ -101,8 +101,9 @@ type Terminal struct {
start chan interface{} start chan interface{}
vterm *vterm.VTerm vterm *vterm.VTerm
damage []vterm.Rect // protected by mutex damage []vterm.Rect // protected by damageMutex
mutex sync.Mutex damageMutex sync.Mutex
writeMutex sync.Mutex
OnClose func(err error) OnClose func(err error)
OnEvent func(event tcell.Event) bool OnEvent func(event tcell.Event) bool
@ -129,7 +130,9 @@ func NewTerminal(cmd *exec.Cmd) (*Terminal, error) {
term.Close(nil) term.Close(nil)
return return
} }
term.writeMutex.Lock()
n, err = term.vterm.Write(buf[:n]) n, err = term.vterm.Write(buf[:n])
term.writeMutex.Unlock()
if err != nil { if err != nil {
term.Close(err) term.Close(err)
return return
@ -204,9 +207,9 @@ func (term *Terminal) Invalidate() {
if term.vterm != nil { if term.vterm != nil {
width, height := term.vterm.Size() width, height := term.vterm.Size()
rect := vterm.NewRect(0, width, 0, height) rect := vterm.NewRect(0, width, 0, height)
term.mutex.Lock() term.damageMutex.Lock()
term.damage = append(term.damage, *rect) term.damage = append(term.damage, *rect)
term.mutex.Unlock() term.damageMutex.Unlock()
} }
term.invalidate() term.invalidate()
} }
@ -247,12 +250,14 @@ func (term *Terminal) Draw(ctx *ui.Context) {
return return
} }
if ctx.Width() != cols || ctx.Height() != rows { if ctx.Width() != cols || ctx.Height() != rows {
term.writeMutex.Lock()
pty.Setsize(term.pty, &winsize) pty.Setsize(term.pty, &winsize)
term.vterm.SetSize(ctx.Height(), ctx.Width()) term.vterm.SetSize(ctx.Height(), ctx.Width())
term.writeMutex.Unlock()
rect := vterm.NewRect(0, ctx.Width(), 0, ctx.Height()) rect := vterm.NewRect(0, ctx.Width(), 0, ctx.Height())
term.mutex.Lock() term.damageMutex.Lock()
term.damage = append(term.damage, *rect) term.damage = append(term.damage, *rect)
term.mutex.Unlock() term.damageMutex.Unlock()
return return
} }
} }
@ -267,7 +272,7 @@ func (term *Terminal) Draw(ctx *ui.Context) {
// naive optimization // naive optimization
visited := make(map[coords]interface{}) visited := make(map[coords]interface{})
term.mutex.Lock() term.damageMutex.Lock()
for _, rect := range term.damage { for _, rect := range term.damage {
for x := rect.StartCol(); x < rect.EndCol() && x < ctx.Width(); x += 1 { for x := rect.StartCol(); x < rect.EndCol() && x < ctx.Width(); x += 1 {
@ -290,7 +295,7 @@ func (term *Terminal) Draw(ctx *ui.Context) {
} }
term.damage = nil term.damage = nil
term.mutex.Unlock() term.damageMutex.Unlock()
if term.focus && !term.closed { if term.focus && !term.closed {
if !term.cursorShown { if !term.cursorShown {
@ -414,9 +419,9 @@ func (term *Terminal) styleFromCell(cell *vterm.ScreenCell) tcell.Style {
} }
func (term *Terminal) onDamage(rect *vterm.Rect) int { func (term *Terminal) onDamage(rect *vterm.Rect) int {
term.mutex.Lock() term.damageMutex.Lock()
term.damage = append(term.damage, *rect) term.damage = append(term.damage, *rect)
term.mutex.Unlock() term.damageMutex.Unlock()
term.invalidate() term.invalidate()
return 1 return 1
} }