rivo / tview

Terminal UI library with rich, interactive widgets — written in Golang
MIT License
11.12k stars 576 forks source link

Changing selection on a cleared table can make the app unresponsive. #944

Closed stijnveenman closed 8 months ago

stijnveenman commented 9 months ago

If we take the following example

package main

import (
    "github.com/gdamore/tcell/v2"
    "github.com/rivo/tview"
)

func main() {
    app := tview.NewApplication()
    table := tview.NewTable().
        SetBorders(true)

    table.SetCell(0, 0, tview.NewTableCell("test").SetSelectable(false))
    table.SetCell(1, 0, tview.NewTableCell("test").SetSelectable(true))
    table.SetCell(2, 0, tview.NewTableCell("test").SetSelectable(true))

    table.SetSelectable(true, false)

    table.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
        if event.Rune() == 'a' {
            table.SetCell(table.GetRowCount(), 0, tview.NewTableCell("test"))
        }
        if event.Rune() == 'c' {
            table.Clear()
            table.SetCell(0, 0, tview.NewTableCell("test").SetSelectable(false))
        }
        return event
    })

    if err := app.SetRoot(table, true).SetFocus(table).Run(); err != nil {
        panic(err)
    }
}

We have row 0; which is not selectable (think of a header in a table) And a few selectable rows. We can add rows by pressing a, and clear with c.

Expected

If we add a few rows this works fine, but if we click c we clear the table and create the (unselectable) header again. Then, we press j to move to a different row, causing the selection to "change".

After this, the app becomes unresponsive. Adding a new row with a does nothing. Even ctr+c does not close the app anymore, and CPU jumps up to 100%.

Side note: if i clear the table with row 2 (3th row) selected, and do not select a different row. And add a few rows again, i can see that row 2 is still selected. And the app stays responsive. It only happens when changing a row.

F1bonacc1 commented 9 months ago

I attached a goroutine profiler. It looks like the table is stuck in this loop: https://github.com/rivo/tview/blob/861aa94d61c899b32a1304d61b840d0178ece408/table.go#L1373

#   0x65ae14    github.com/rivo/tview.(*Table).InputHandler.func1.2+0x54            github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/table.go:1375
#   0x65aca3    github.com/rivo/tview.(*Table).InputHandler.func1.5+0xa3            github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/table.go:1440
#   0x65a5a4    github.com/rivo/tview.(*Table).InputHandler.func1+0x4e4             github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/table.go:1598
#   0x65a08f    github.com/rivo/tview.(*Table).InputHandler.(*Box).WrapInputHandler.func2+0x4f  github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/box.go:167
#   0x63bb16    github.com/rivo/tview.(*Grid).InputHandler.func1+0x1b6              github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/grid.go:277
#   0x63b92f    github.com/rivo/tview.(*Grid).InputHandler.(*Box).WrapInputHandler.func2+0x4f   github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/box.go:167
#   0x650801    github.com/rivo/tview.(*Pages).InputHandler.func1+0xa1              github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/pages.go:311
#   0x65072f    github.com/rivo/tview.(*Pages).InputHandler.(*Box).WrapInputHandler.func2+0x4f  github.com/rivo/tview@v0.0.0-20240101144852-b3bd1aa5e9f2/box.go:167
#   0x627737    github.com/rivo/tview.(*Application).Run+0x557  
rivo commented 8 months ago

Thank you. This should be fixed with the latest commit.