mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-10-26 15:10:20 -05:00
Restore the terminal if a goroutine panics
Most goroutines run their function through utils.Safe, which closes the screen if the function panics. Without it, the panic is printed to a terminal that is still in raw mode and on the alternate screen, and the terminal needs a reset afterwards. Go has no process-wide hook for panics, so every goroutine has to do this itself. Use utils.Safe for the goroutines that don't use it yet. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
6042e1c28b
commit
73fac4a554
10 files changed
+23
-20
No files matched your search
@@ -166,11 +166,11 @@ func Start(buildInfo *BuildInfo, integrationTest integrationTypes.IntegrationTes
|
||||
}
|
||||
|
||||
if cliArgs.Profile {
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
if err := http.ListenAndServe("localhost:6060", nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
parsedGitArg := parseGitArg(cliArgs.GitArg)
|
||||
|
||||
@@ -207,7 +207,7 @@ func (p *winPty) Close() error {
|
||||
func startWaiter(proc *os.Process, p *winPty) func() error {
|
||||
done := make(chan struct{})
|
||||
var waitErr error
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
defer close(done)
|
||||
state, err := proc.Wait()
|
||||
p.closeHpc()
|
||||
@@ -218,7 +218,7 @@ func startWaiter(proc *os.Process, p *winPty) func() error {
|
||||
if !state.Success() {
|
||||
waitErr = fmt.Errorf("exit status %d", state.ExitCode())
|
||||
}
|
||||
}()
|
||||
})
|
||||
return func() error {
|
||||
<-done
|
||||
return waitErr
|
||||
|
||||
@@ -280,13 +280,13 @@ func (self *FixupHelper) blameDeletedLines(deletedLineHunks []*hunk) ([]string,
|
||||
})
|
||||
}
|
||||
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
// We don't care about the error here, we'll check it later (in the
|
||||
// return statement below). Here we only wait for all the goroutines to
|
||||
// finish so that we can close the channel.
|
||||
_ = errg.Wait()
|
||||
close(hashChan)
|
||||
}()
|
||||
})
|
||||
|
||||
result := set.New[string]()
|
||||
for hash := range hashChan {
|
||||
@@ -343,13 +343,13 @@ func (self *FixupHelper) blameAddedLines(commits []*models.Commit, addedLineHunk
|
||||
})
|
||||
}
|
||||
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
// We don't care about the error here, we'll check it later (in the
|
||||
// return statement below). Here we only wait for all the goroutines to
|
||||
// finish so that we can close the channel.
|
||||
_ = errg.Wait()
|
||||
close(hashesChan)
|
||||
}()
|
||||
})
|
||||
|
||||
result := set.New[string]()
|
||||
for hashes := range hashesChan {
|
||||
|
||||
@@ -324,10 +324,10 @@ func (self *ReposHelper) CreateRecentReposMenu() error {
|
||||
wg.Add(len(recentRepoPaths))
|
||||
|
||||
for i, path := range recentRepoPaths {
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
defer wg.Done()
|
||||
currentBranches[i] = self.getCurrentBranch(path)
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
@@ -45,7 +46,7 @@ func handleResumeSignal(log *logrus.Entry, onResume func() error) {
|
||||
}
|
||||
|
||||
func installResumeSignalHandler(log *logrus.Entry, onResume func() error) {
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGCONT)
|
||||
|
||||
@@ -55,5 +56,5 @@ func installResumeSignalHandler(log *logrus.Entry, onResume func() error) {
|
||||
handleResumeSignal(log, onResume)
|
||||
}
|
||||
}
|
||||
}()
|
||||
})
|
||||
}
|
||||
@@ -80,7 +80,7 @@ func RenderAux(pipeSets [][]Pipe, commits []*models.Commit, selectedCommitHashPt
|
||||
wg.Add(maxProcs)
|
||||
|
||||
for i := range maxProcs {
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
from := i * perProc
|
||||
to := (i + 1) * perProc
|
||||
if i == maxProcs-1 {
|
||||
@@ -98,7 +98,7 @@ func RenderAux(pipeSets [][]Pipe, commits []*models.Commit, selectedCommitHashPt
|
||||
}
|
||||
chunks[i] = innerLines
|
||||
wg.Done()
|
||||
}()
|
||||
})
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/jesseduffield/lazygit/pkg/gocui"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/presentation"
|
||||
"github.com/jesseduffield/lazygit/pkg/gui/types"
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
"github.com/sasha-s/go-deadlock"
|
||||
)
|
||||
@@ -64,12 +65,12 @@ func (self *StatusManager) WithWaitingStatus(message string, renderFunc func(),
|
||||
func (self *StatusManager) AddToastStatus(message string, kind types.ToastKind) int {
|
||||
id := self.addStatus(message, "toast", kind)
|
||||
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
delay := lo.Ternary(kind == types.ToastKindError, time.Second*4, time.Second*2)
|
||||
time.Sleep(delay)
|
||||
|
||||
self.removeStatus(id)
|
||||
}()
|
||||
})
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func (gui *Gui) handleTestMode() {
|
||||
gui.c.GocuiGui().WaitUntilIdle()
|
||||
}
|
||||
|
||||
go func() {
|
||||
go utils.Safe(func() {
|
||||
waitUntilIdle()
|
||||
|
||||
toastChan := make(chan string, 100)
|
||||
@@ -43,7 +43,7 @@ func (gui *Gui) handleTestMode() {
|
||||
|
||||
// Wait for the event loop to actually exit.
|
||||
<-gui.g.LoopExited()
|
||||
}()
|
||||
})
|
||||
|
||||
if os.Getenv(components.WAIT_FOR_DEBUGGER_ENV_VAR) == "" {
|
||||
timeout := 40 * time.Second * testTimeoutMultiplier
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
@@ -77,7 +78,7 @@ func NewGame(width, height int, render func(cells [][]CellType, alive bool), log
|
||||
}
|
||||
|
||||
func (self *Game) Start() {
|
||||
go self.gameLoop()
|
||||
go utils.Safe(self.gameLoop)
|
||||
}
|
||||
|
||||
func (self *Game) Exit() {
|
||||
|
||||
+1
-1
@@ -818,7 +818,7 @@ func (self *ViewBufferManager) NewCmdTask(start func() (Cmd, io.Reader), prefix
|
||||
// the process takes a while until it actually terminates. We still want to call
|
||||
// Wait to reclaim any resources, but do it on a background goroutine, and ignore
|
||||
// any errors.
|
||||
go func() { _ = cmd.Wait() }()
|
||||
go utils.Safe(func() { _ = cmd.Wait() })
|
||||
default:
|
||||
if err := cmd.Wait(); err != nil {
|
||||
self.Log.Errorf("Unexpected error when running cmd task: %v; Failed command: %v", err, cmd.String())
|
||||
|
||||
Reference in new issue
Block a user