From 0d318364222fb17d2748440800106ef3d8879cf4 Mon Sep 17 00:00:00 2001 From: Nacho Date: Tue, 13 Oct 2026 21:19:16 +0200 Subject: [PATCH] fix(longops): drain process output before Wait to avoid truncated lines With StdoutPipe, Wait closes the read end of the pipe as soon as the process exits, so calling Wait before draining the scanner could lose whatever was still buffered: on a loaded arm64 runner the release CI hit lines=[] for a printf that wrote and exited immediately (#150). Read to EOF first, then reap. Closes #150 --- internal/longops/longops.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/longops/longops.go b/internal/longops/longops.go index 0042971..304131c 100644 --- a/internal/longops/longops.go +++ b/internal/longops/longops.go @@ -113,6 +113,12 @@ func (m *Manager) Start(typ, target, name string, args ...string) (*Op, error) { // watch consume la salida línea a línea y cierra el ciclo de vida de la op. func (m *Manager) watch(op *Op, cmd *exec.Cmd, stdout io.Reader) { + // Drenar la salida a EOF ANTES de Wait(): con StdoutPipe, Wait cierra el + // extremo de lectura de la tubería al ver salir el proceso, así que llamar + // Wait antes de agotar las lecturas puede truncar lo buffered (en un + // runner cargado se vio lines=[] con un printf que escribía y moría ya). + // EOF llega solo cuando el proceso cierra su stdout al morir, así que + // este orden garantiza capturar TODAS las líneas antes de reapsar. scanDone := make(chan struct{}) go func() { defer close(scanDone) @@ -122,8 +128,8 @@ func (m *Manager) watch(op *Op, cmd *exec.Cmd, stdout io.Reader) { m.appendLine(op, sc.Text()) } }() - err := cmd.Wait() <-scanDone + err := cmd.Wait() ended := time.Now().UTC() m.mu.Lock() op.Ended = &ended