m/p/cmd: handle exiting processes
RunCommand was seen waiting for the line that would trigger its
supplied predicate function even after the managed process exited,
which is deemed a bad strategy.
Change-Id: I5fa5add1daf3c4f0c69f72f5b5859e88f7bc2679
Reviewed-on: https://review.monogon.dev/c/monogon/+/847
Reviewed-by: Sergiusz Bazanski <serge@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/pkg/cmd/run.go b/metropolis/pkg/cmd/run.go
index 7591d56..f92cb84 100644
--- a/metropolis/pkg/cmd/run.go
+++ b/metropolis/pkg/cmd/run.go
@@ -14,9 +14,11 @@
)
// RunCommand starts a new process and waits until either its completion, or
-// until the supplied predicate function returns true. The function is called
+// until the supplied predicate function pf returns true. The function is called
// for each line produced by the new process.
//
+// The returned boolean value equals the last value returned by pf.
+//
// The process will be killed both in the event the context is cancelled, and
// when expectedOutput is found.
func RunCommand(ctx context.Context, path string, args []string, pf func(string) bool) (bool, error) {
@@ -50,6 +52,13 @@
return false, fmt.Errorf("couldn't start the process: %w", err)
}
+ // Handle the case in which the process finishes before pf takes the chance to
+ // kill it.
+ complC := make(chan error, 1)
+ go func() {
+ complC <- cmd.Wait()
+ }()
+
// Try matching against expectedOutput and return the result.
for {
select {
@@ -61,6 +70,8 @@
cmd.Wait()
return true, nil
}
+ case err := <-complC:
+ return false, err
}
}
}