From 2b57733541c0b80e5e27c76012df5fdf3d762639 Mon Sep 17 00:00:00 2001 From: Stefan Haller Date: Mon, 5 Oct 2026 16:10:20 +0200 Subject: [PATCH] Hoist the check for a stopped task to the top of NewCmdTask The next commit checks whether the task was stopped once more before the command starts. Use the same check there as in the loop that reads the command's output. Co-Authored-By: Claude Opus 5.5 (1M context) --- pkg/tasks/tasks.go | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/pkg/tasks/tasks.go b/pkg/tasks/tasks.go index c2b8177d0..307b64834 100644 --- a/pkg/tasks/tasks.go +++ b/pkg/tasks/tasks.go @@ -448,11 +448,18 @@ func (self *ViewBufferManager) NewCmdTask(start func() (Cmd, io.Reader), prefix time.Sleep(THROTTLE_TIME) } - select { - case <-opts.Stop: + stopped := func() bool { + select { + case <-opts.Stop: + return true + default: + return false + } + } + + if stopped() { onDone() return nil - default: } startTime := time.Now() @@ -573,22 +580,6 @@ func (self *ViewBufferManager) NewCmdTask(start func() (Cmd, io.Reader), prefix } } - // Go's select picks randomly among ready cases, so once opts.Stop is - // closed the selects below could still service a ready data channel - // instead of bailing. Check stop explicitly first to give it priority: - // a task that's been stopped (it's being replaced by a newer one) must - // not touch the view here — it would start an off-screen render and - // write the prefix into it, clobbering what the incoming task is about - // to render. - stopped := func() bool { - select { - case <-opts.Stop: - return true - default: - return false - } - } - // The total number of lines we have read so far. Requests specify an // absolute target total (see LinesToRead.Total), so we compare against // this to work out how many more lines, if any, we still need to read. @@ -637,6 +628,13 @@ func (self *ViewBufferManager) NewCmdTask(start func() (Cmd, io.Reader), prefix } } + // Go's select picks randomly among ready cases, so once opts.Stop is + // closed the selects below could still service a ready data channel + // instead of bailing. Check stop explicitly first to give it priority: + // a task that's been stopped (it's being replaced by a newer one) must + // not touch the view here — it would start an off-screen render and + // write the prefix into it, clobbering what the incoming task is about + // to render. outer: for { if stopped() {