in machine.go [679:723]
func (m *Machine) captureFifoToFileWithChannel(ctx context.Context, logger *log.Entry, fifoPath string, w io.Writer, done chan error) error {
// open the fifo pipe which will be used
// to write its contents to a file.
fifoPipe, err := fifo.OpenFifo(ctx, fifoPath, syscall.O_RDONLY|syscall.O_NONBLOCK, 0600)
if err != nil {
return fmt.Errorf("Failed to open fifo path at %q: %v", fifoPath, err)
}
logger.Debugf("Capturing %q to writer", fifoPath)
// this goroutine is to track the life of the application along with whether
// or not the context has been cancelled which is signified by the exitCh. In
// the event that the exitCh has been closed, we will close the fifo file.
go func() {
<-m.exitCh
if err := fifoPipe.Close(); err != nil {
logger.WithError(err).Debug("failed to close fifo")
}
}()
// Uses a goroutine to copy the contents of the fifo pipe to the io.Writer.
// In the event that the goroutine finishes, which is caused by either the
// context being closed or the application being closed, we will close the
// pipe and unlink the fifo path.
go func() {
defer func() {
if err := fifoPipe.Close(); err != nil {
logger.Warnf("Failed to close fifo pipe: %v", err)
}
if err := syscall.Unlink(fifoPath); err != nil {
logger.Warnf("Failed to unlink %s: %v", fifoPath, err)
}
}()
if _, err := io.Copy(w, fifoPipe); err != nil {
logger.WithError(err).Warn("io.Copy failed to copy contents of fifo pipe")
done <- err
}
close(done)
}()
return nil
}