Here's my code (writeFromProcessToFileWithMax
is an internal function, and is working properly):
// Go routines for non-blocking reading of stdout and stderr and writing to files
g := new(errgroup.Group)
// Read stdout in goroutine.
g.Go(func() error {
err = writeFromProcessToFileWithMax(stdoutScanner, stdoutFileWriter, maxStdoutFileLengthInGB)
if err != nil {
log.Error().Err(err).Msgf("Error writing to stdout file: %s", stdoutFilename)
return err
}
return nil
})
// Read stderr in goroutine.
g.Go(func() error {
err = writeFromProcessToFileWithMax(stderrScanner, stderrFileWriter, maxStderrFileLengthInGB)
if err != nil {
log.Error().Err(err).Msgf("Error writing to stderr file: %s", stderrFilename)
return err
}
return nil
})
// Wait the command in a goroutine.
g.Go(func() error {
return cmd.Wait()
})
// Starting the command
if err = cmd.Start(); err != nil {
log.Error().Err(err).Msg("Error starting command")
return err
}
// Waiting until errorGroups groups are done
if err = g.Wait(); err != nil {
log.Error().Err(err).Msg("Error during running of the command")
}
When I run it, I get the following Error = Error during running of the command error="exec: not started"
. But everything works properly.
Will the come back to bite me or should I suppress?
You're waiting for cmd
before you start it. cmd.Wait()
would be invoked before cmd.Start()
most of the time in your old code. (There is no guarantee when exactly exactly things in two different goroutines happen with respect to each other, unless you explicitly use synchronisation points)
Swap the order of cmd.Start()
and the cmd.Wait()
inside the goroutine:
// Starting the command
if err = cmd.Start(); err != nil {
log.Error().Err(err).Msg("Error starting command")
return err
}
// Wait the command in a goroutine.
g.Go(func() error {
return cmd.Wait()
})
When you start the goroutine that waits after starting the command, you're guaranteed to perform cmd.Start()
and cmd.Wait()
in the correct order.
As to why it seemed to work: g.Wait()
"blocks until all function calls from the Go method have returned, then returns the first non-nil error (if any) from them."
So all the go routines complete, including the ones that copy the output, and then you see the error from the one that did the cmd.Wait()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With