diff --git a/pkg/process/io.go b/pkg/process/io.go index 0603ffff0..914efd002 100644 --- a/pkg/process/io.go +++ b/pkg/process/io.go @@ -246,11 +246,12 @@ func (c *countingWriteCloser) Close() error { } // NewBinaryIO runs a custom binary process for pluggable shim logging -func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error) { +func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (_ runc.IO, err error) { ns, err := namespaces.NamespaceRequired(ctx) if err != nil { return nil, err } + var args []string for k, vs := range uri.Query() { args = append(args, k) @@ -259,20 +260,35 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error) } } + var closers []func() error + defer func() { + if err == nil { + return + } + result := multierror.Append(err) + for _, fn := range closers { + result = multierror.Append(result, fn()) + } + err = multierror.Flatten(result) + }() + out, err := newPipe() if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to create stdout pipes") } + closers = append(closers, out.Close) serr, err := newPipe() if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to create stderr pipes") } + closers = append(closers, serr.Close) r, w, err := os.Pipe() if err != nil { return nil, err } + closers = append(closers, r.Close, w.Close) cmd := exec.Command(uri.Path, args...) cmd.Env = append(cmd.Env, @@ -284,17 +300,21 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error) // don't need to register this with the reaper or wait when // running inside a shim if err := cmd.Start(); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to start binary process") } + closers = append(closers, func() error { return cmd.Process.Kill() }) + // close our side of the pipe after start if err := w.Close(); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to close write pipe after start") } + // wait for the logging binary to be ready b := make([]byte, 1) if _, err := r.Read(b); err != nil && err != io.EOF { - return nil, err + return nil, errors.Wrap(err, "failed to read from logging binary") } + return &binaryIO{ cmd: cmd, out: out, @@ -423,9 +443,15 @@ type pipe struct { } func (p *pipe) Close() error { - err := p.w.Close() - if rerr := p.r.Close(); err == nil { - err = rerr + var result *multierror.Error + + if err := p.w.Close(); err != nil { + result = multierror.Append(result, errors.Wrap(err, "failed to close write pipe")) } - return err + + if err := p.r.Close(); err != nil { + result = multierror.Append(result, errors.Wrap(err, "failed to close read pipe")) + } + + return multierror.Prefix(result.ErrorOrNil(), "pipe:") }