[GH-ISSUE #932] Using app.Suspend() make application unresponsive #681

Closed
opened 2026-03-04 01:06:59 +03:00 by kerem · 5 comments
Owner

Originally created by @saeedafzal on GitHub (Dec 31, 2023).
Original GitHub issue: https://github.com/rivo/tview/issues/932

Hi, I've ran into an issue where after using app.Suspend(...) to start vim, the application stops responding to any keys and mouse. I can't CTRL+C to exit the app either.

From this issue, https://github.com/rivo/tview/issues/244 from what I can tell, some people suggest adding app.Sync() after app.Suspend() which seems to have worked for some, but it didn't seem to work in my case.

I'm using Arch Linux and Kitty terminal emulator. Also happens with Alacritty. And I tested this on my M2 MacBook pro with Kitty and I get the same issue.

Video showing issue (recorded on the Mac):

https://github.com/rivo/tview/assets/37543494/606cbe3c-14ef-44a5-abfc-df4bff634af8

The code I ran in the video above (standalone):

package main

import (
	"os"
	"os/exec"

	"github.com/rivo/tview"
)

func main() {
	app := tview.
		NewApplication().
		EnableMouse(true)

	input := tview.NewInputField()

	// Starts vim using app.Suspend(...)
	startVim := func() {
		filename := "temp"
		file, err := os.Create(filename)
		if err != nil {
			panic(err)
		}
		defer file.Close()
		defer os.Remove(filename)

		app.Suspend(func() {
			cmd := exec.Command("vim", filename)
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr

			if err := cmd.Run(); err != nil {
				panic(err)
			}
		})
		app.Sync()

		b, err := os.ReadFile(filename)
		if err != nil {
			panic(err)
		}

		input.SetText(string(b))
	}

	form := tview.NewForm().
		AddFormItem(input).
		AddButton("Start Vim", startVim).
		AddButton("Button 2", nil)

	if err := app.SetRoot(form, true).Run(); err != nil {
		panic(err)
	}
}
Originally created by @saeedafzal on GitHub (Dec 31, 2023). Original GitHub issue: https://github.com/rivo/tview/issues/932 Hi, I've ran into an issue where after using `app.Suspend(...)` to start vim, the application stops responding to any keys and mouse. I can't CTRL+C to exit the app either. From this issue, https://github.com/rivo/tview/issues/244 from what I can tell, some people suggest adding `app.Sync()` after `app.Suspend()` which seems to have worked for some, but it didn't seem to work in my case. I'm using Arch Linux and Kitty terminal emulator. Also happens with Alacritty. And I tested this on my M2 MacBook pro with Kitty and I get the same issue. Video showing issue (recorded on the Mac): https://github.com/rivo/tview/assets/37543494/606cbe3c-14ef-44a5-abfc-df4bff634af8 The code I ran in the video above (standalone): ```go package main import ( "os" "os/exec" "github.com/rivo/tview" ) func main() { app := tview. NewApplication(). EnableMouse(true) input := tview.NewInputField() // Starts vim using app.Suspend(...) startVim := func() { filename := "temp" file, err := os.Create(filename) if err != nil { panic(err) } defer file.Close() defer os.Remove(filename) app.Suspend(func() { cmd := exec.Command("vim", filename) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { panic(err) } }) app.Sync() b, err := os.ReadFile(filename) if err != nil { panic(err) } input.SetText(string(b)) } form := tview.NewForm(). AddFormItem(input). AddButton("Start Vim", startVim). AddButton("Button 2", nil) if err := app.SetRoot(form, true).Run(); err != nil { panic(err) } } ```
kerem closed this issue 2026-03-04 01:06:59 +03:00
Author
Owner

@saeedafzal commented on GitHub (Jan 1, 2024):

Hi @digitallyserviced, that's quite interesting, I've looked at those examples and I've actually found the issue thanks to it. It seems like the problem is the version of tcell that I was using.

I was running the example code I posted above with tcell v2.7.0, which is the latest version at this time, which is why I got the issue. Probably because I did go get -u github.com/rivo/tview which also updated tcell.

But if I use the version of tcell from tview's go.mod, which is 2.6.x, then everything works fine, including my example above. So the issue seems to be that I was using the latest version of tcell, when I should have been using the version that tview pulls in. Not sure what version of tcell you used to run the example, but I'm guessing it wasn't the latest one.

So for anyone else having this issue, don't upgrade tcell yourself. Only upgrade it with tview, at least that makes it work for me.

<!-- gh-comment-id:1873461616 --> @saeedafzal commented on GitHub (Jan 1, 2024): Hi @digitallyserviced, that's quite interesting, I've looked at those examples and I've actually found the issue thanks to it. It seems like the problem is the version of tcell that I was using. I was running the example code I posted above with tcell v2.7.0, which is the latest version at this time, which is why I got the issue. Probably because I did `go get -u github.com/rivo/tview` which also updated tcell. But if I use the version of tcell from tview's go.mod, which is 2.6.x, then everything works fine, including my example above. So the issue seems to be that I was using the latest version of tcell, when I should have been using the version that tview pulls in. Not sure what version of tcell you used to run the example, but I'm guessing it wasn't the latest one. So for anyone else having this issue, don't upgrade tcell yourself. Only upgrade it with tview, at least that makes it work for me.
Author
Owner

@rosmanov commented on GitHub (Jan 3, 2024):

I can confirm that the app.Suspend() method renders the application unresponsive with github.com/gdamore/tcell/v2 v2.7.0.

Here is how I see the problem with tcell. In a tview app, we often need to refer to the github.com/gdamore/tcell/v2 package (e.g., tcell.KeyF1, func(event *tcell.EventKey), etc.). To do that, we install the tcell package as a separate dependency. When a new version of tcell is released, a dependency monitoring system (such as Dependabot) generates a PR to update the dependency to the latest stable version. However, there is no indication of compatibility between the tcell and tview versions. So we just merge the PR and hope for the best.

I don't know how to solve this problem elegantly. The only idea that comes to mind is wrapping the entire tcell public API so that the user could only refer to tview when using the tview API. This way, the tcell dependency might become an implicit dependency pulled by tview.

Here is another code demonstrating the issue:

package main

import (
	"os"
	"os/exec"

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

func main() {

	box := tview.NewBox().SetBorder(true).SetTitle("Hello, world!")
	app := tview.NewApplication()

	app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
		switch event.Key() {
		case tcell.KeyF1, tcell.KeyCtrlH:
			app.Suspend(func() {
				cmd := exec.Command("vim", "/tmp/foo")
				cmd.Stdout = os.Stdout
				cmd.Stdin = os.Stdin
				_ = cmd.Run()
			})
		case tcell.KeyCtrlQ:
			app.Stop()
			return nil
		}
		return event

	})

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

go.mod

module example.com/m

go 1.21.5

require (
        github.com/gdamore/tcell/v2 v2.7.0 // indirect
        github.com/rivo/tview v0.0.0-20240101144852-b3bd1aa5e9f2
)

require (
        github.com/gdamore/encoding v1.0.0 // indirect
        github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
        github.com/mattn/go-runewidth v0.0.15 // indirect
        github.com/rivo/uniseg v0.4.3 // indirect
        golang.org/x/sys v0.15.0 // indirect
        golang.org/x/term v0.15.0 // indirect
        golang.org/x/text v0.14.0 // indirect
)

Steps:

  1. go run main.go
  2. Press the F1 key
  3. Exit vim: :q
  4. Try to invoke vim again by pressing the F1 key or exiting the app by invoking the shortcut Ctrl+Q.

Actual result:

After closing vim, the app doesn't respond to key presses.

Expected result:

The app should resume after the vim process exits so that the user is able to either quit the app with Ctrl+Q or run another vim process by pressing F1.

<!-- gh-comment-id:1875002574 --> @rosmanov commented on GitHub (Jan 3, 2024): I can confirm that the `app.Suspend()` method renders the application unresponsive with `github.com/gdamore/tcell/v2 v2.7.0`. Here is how I see the problem with tcell. In a tview app, we often need to refer to the `github.com/gdamore/tcell/v2` package (e.g., `tcell.KeyF1`, `func(event *tcell.EventKey)`, etc.). To do that, we install the tcell package as a separate dependency. When a new version of tcell is released, a dependency monitoring system (such as Dependabot) generates a PR to update the dependency to the latest stable version. However, there is no indication of compatibility between the tcell and tview versions. So we just merge the PR and hope for the best. I don't know how to solve this problem elegantly. The only idea that comes to mind is wrapping the entire tcell public API so that the user could only refer to tview when using the tview API. This way, the tcell dependency might become an implicit dependency pulled by tview. Here is another code demonstrating the issue: ```go package main import ( "os" "os/exec" "github.com/rivo/tview" "github.com/gdamore/tcell/v2" ) func main() { box := tview.NewBox().SetBorder(true).SetTitle("Hello, world!") app := tview.NewApplication() app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { switch event.Key() { case tcell.KeyF1, tcell.KeyCtrlH: app.Suspend(func() { cmd := exec.Command("vim", "/tmp/foo") cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin _ = cmd.Run() }) case tcell.KeyCtrlQ: app.Stop() return nil } return event }) if err := app.SetRoot(box, true).Run(); err != nil { panic(err) } } ``` go.mod ``` module example.com/m go 1.21.5 require ( github.com/gdamore/tcell/v2 v2.7.0 // indirect github.com/rivo/tview v0.0.0-20240101144852-b3bd1aa5e9f2 ) require ( github.com/gdamore/encoding v1.0.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/uniseg v0.4.3 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect ) ``` **Steps:** 1. `go run main.go` 2. Press the F1 key 3. Exit vim: `:q` 4. Try to invoke vim again by pressing the F1 key or exiting the app by invoking the shortcut Ctrl+Q. **Actual result:** After closing vim, the app doesn't respond to key presses. **Expected result:** The app should resume after the vim process exits so that the user is able to either quit the app with Ctrl+Q or run another vim process by pressing F1.
Author
Owner

@ilikeorangutans commented on GitHub (Jan 7, 2024):

I have the same issue. Calling app.Suspend() freezes (deadlocks?) the app on return.

go 1.21.5, tcell 2.7.0, tview 5f07813844.

<!-- gh-comment-id:1879897237 --> @ilikeorangutans commented on GitHub (Jan 7, 2024): I have the same issue. Calling `app.Suspend()` freezes (deadlocks?) the app on return. go 1.21.5, tcell 2.7.0, tview 5f078138442e.
Author
Owner

@rivo commented on GitHub (Jan 11, 2024):

See https://github.com/gdamore/tcell/issues/677.

<!-- gh-comment-id:1886770641 --> @rivo commented on GitHub (Jan 11, 2024): See https://github.com/gdamore/tcell/issues/677.
Author
Owner

@dundee commented on GitHub (Feb 18, 2024):

Looks like this is now fixed and released in https://github.com/gdamore/tcell/releases/tag/v2.7.1

<!-- gh-comment-id:1951147187 --> @dundee commented on GitHub (Feb 18, 2024): Looks like this is now fixed and released in https://github.com/gdamore/tcell/releases/tag/v2.7.1
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#681
No description provided.