~sircmpwn/aerc

3445b80d7a710edf72088d6faea1f640988b1766 — Kevin Kuehler 1 year, 1 month ago 0bfb90b
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>
1 files changed, 15 insertions(+), 10 deletions(-)

M widgets/terminal.go
M widgets/terminal.go => widgets/terminal.go +15 -10
@@ 101,8 101,9 @@ type Terminal struct {
	start       chan interface{}
	vterm       *vterm.VTerm

	damage []vterm.Rect // protected by mutex
	mutex  sync.Mutex
	damage []vterm.Rect // protected by damageMutex
	damageMutex sync.Mutex
	writeMutex  sync.Mutex

	OnClose func(err error)
	OnEvent func(event tcell.Event) bool


@@ 129,7 130,9 @@ func NewTerminal(cmd *exec.Cmd) (*Terminal, error) {
				term.Close(nil)
				return
			}
			term.writeMutex.Lock()
			n, err = term.vterm.Write(buf[:n])
			term.writeMutex.Unlock()
			if err != nil {
				term.Close(err)
				return


@@ 204,9 207,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.damageMutex.Lock()
		term.damage = append(term.damage, *rect)
		term.mutex.Unlock()
		term.damageMutex.Unlock()
	}
	term.invalidate()
}


@@ 247,12 250,14 @@ func (term *Terminal) Draw(ctx *ui.Context) {
			return
		}
		if ctx.Width() != cols || ctx.Height() != rows {
			term.writeMutex.Lock()
			pty.Setsize(term.pty, &winsize)
			term.vterm.SetSize(ctx.Height(), ctx.Width())
			term.writeMutex.Unlock()
			rect := vterm.NewRect(0, ctx.Width(), 0, ctx.Height())
			term.mutex.Lock()
			term.damageMutex.Lock()
			term.damage = append(term.damage, *rect)
			term.mutex.Unlock()
			term.damageMutex.Unlock()
			return
		}
	}


@@ 267,7 272,7 @@ func (term *Terminal) Draw(ctx *ui.Context) {
	// naive optimization
	visited := make(map[coords]interface{})

	term.mutex.Lock()
	term.damageMutex.Lock()
	for _, rect := range term.damage {
		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.mutex.Unlock()
	term.damageMutex.Unlock()

	if term.focus && !term.closed {
		if !term.cursorShown {


@@ 414,9 419,9 @@ func (term *Terminal) styleFromCell(cell *vterm.ScreenCell) tcell.Style {
}

func (term *Terminal) onDamage(rect *vterm.Rect) int {
	term.mutex.Lock()
	term.damageMutex.Lock()
	term.damage = append(term.damage, *rect)
	term.mutex.Unlock()
	term.damageMutex.Unlock()
	term.invalidate()
	return 1
}