mirror of
https://github.com/jesseduffield/lazygit.git
synced 2026-09-10 07:36:27 -04:00
Never hand NewCmdTask a nil reader when a command fails to start
NewCmdTask feeds the reader returned by its start func into a bufio.Scanner, and Scanner.Scan panics with a nil pointer dereference when that reader is nil. Two start funcs could produce one: - newPtyTask's fallback for a failed StartPty returned a literal nil reader, alongside an ExecCmd that was never started, so the intended "fall back to a plain cmd task" never worked. This crashed lazygit on Windows when using a custom pager with the main view zero-sized, e.g. after pressing + twice to enter full-screen mode with a side panel focused: ConPTY rejects zero dimensions, making StartPty fail. - startCmdWithPipe returned nil when the pipe couldn't be created, which the Unix pty fallback path can trigger, since a failed pty start can leave the tty assigned to the command's stdout. Make startCmdWithPipe never return a nil reader: when the pipe can't be created, don't start the command at all and return an empty reader so the task shuts down cleanly with the error in the log. Then route newPtyTask's fallback through it, so a StartPty failure degrades to running the command without a pty: the pager is lost, but the command's output still renders. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
400faea60c
commit
f000ce9f1c
|
|
@ -100,6 +100,7 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
|||
cols, rows := gui.desiredPtySize(view)
|
||||
|
||||
var p oscommands.Pty
|
||||
var fallbackPipe io.ReadCloser
|
||||
start := func() (tasks.Cmd, io.Reader) {
|
||||
// The pty (and pager) wrap to this width; apply it here, on the
|
||||
// task's goroutine once the previous task has stopped, so it doesn't
|
||||
|
|
@ -109,7 +110,11 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
|||
sp, err := oscommands.StartPty(cmd, cols, rows)
|
||||
if err != nil {
|
||||
gui.c.Log.Error(err)
|
||||
return tasks.ExecCmd{Cmd: cmd}, nil
|
||||
// Fall back to running the command without a pty: the pager is
|
||||
// lost, but the command's output still renders.
|
||||
execCmd, pipe := startCmdWithPipe(cmd, gui.c.Log)
|
||||
fallbackPipe = pipe
|
||||
return execCmd, pipe
|
||||
}
|
||||
p = sp.Pty
|
||||
|
||||
|
|
@ -125,6 +130,10 @@ func (gui *Gui) newPtyTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
|||
if p != nil {
|
||||
p.Close()
|
||||
}
|
||||
if fallbackPipe != nil {
|
||||
fallbackPipe.Close()
|
||||
fallbackPipe = nil
|
||||
}
|
||||
delete(gui.viewPtmxMap, view.Name())
|
||||
gui.Mutexes.PtyMutex.Unlock()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,12 +52,15 @@ func (gui *Gui) newCmdTask(view *gocui.View, cmd *exec.Cmd, prefix string) error
|
|||
|
||||
// startCmdWithPipe starts cmd with its stdout and stderr going to a single
|
||||
// pipe, and returns the command along with the pipe's read end, in the shape
|
||||
// that NewCmdTask expects from its start func.
|
||||
// that NewCmdTask expects from its start func. It never returns a nil reader,
|
||||
// because NewCmdTask's scanner panics on one: when the pipe can't be created
|
||||
// the command isn't started at all, and an empty reader is returned so that
|
||||
// the task shuts down cleanly with the error in the log.
|
||||
func startCmdWithPipe(cmd *exec.Cmd, log *logrus.Entry) (tasks.Cmd, io.ReadCloser) {
|
||||
r, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
r = nil
|
||||
return tasks.ExecCmd{Cmd: cmd}, io.NopCloser(strings.NewReader(""))
|
||||
}
|
||||
cmd.Stderr = cmd.Stdout
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,5 @@ func TestStartCmdWithPipeWhenPipeCannotBeCreated(t *testing.T) {
|
|||
|
||||
// NewCmdTask's scanner panics on a nil reader, so startCmdWithPipe must
|
||||
// not return one even when it can't create the pipe.
|
||||
/* EXPECTED:
|
||||
assert.NotNil(t, r)
|
||||
ACTUAL: */
|
||||
assert.Nil(t, r)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue