Guarantee err results are released when result proxy is released

Signed-off-by: Edgar Lee <edgarl@netflix.com>
v0.8
Edgar Lee 2020-11-25 11:26:53 -08:00
parent b0ed56c6d0
commit 372df78cc8
2 changed files with 33 additions and 30 deletions

View File

@ -16,6 +16,7 @@ import (
"github.com/moby/buildkit/session" "github.com/moby/buildkit/session"
"github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/errdefs" "github.com/moby/buildkit/solver/errdefs"
llberrdefs "github.com/moby/buildkit/solver/llbsolver/errdefs"
"github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/flightcontrol" "github.com/moby/buildkit/util/flightcontrol"
"github.com/moby/buildkit/worker" "github.com/moby/buildkit/worker"
@ -144,41 +145,58 @@ func (b *llbBridge) Solve(ctx context.Context, req frontend.SolveRequest, sid st
} }
type resultProxy struct { type resultProxy struct {
cb func(context.Context) (solver.CachedResult, error) cb func(context.Context) (solver.CachedResult, error)
def *pb.Definition def *pb.Definition
g flightcontrol.Group g flightcontrol.Group
mu sync.Mutex mu sync.Mutex
released bool released bool
v solver.CachedResult v solver.CachedResult
err error err error
errResults []solver.Result
} }
func newResultProxy(b *llbBridge, req frontend.SolveRequest) *resultProxy { func newResultProxy(b *llbBridge, req frontend.SolveRequest) *resultProxy {
return &resultProxy{ rp := &resultProxy{
def: req.Definition, def: req.Definition,
cb: func(ctx context.Context) (solver.CachedResult, error) {
return b.loadResult(ctx, req.Definition, req.CacheImports)
},
} }
rp.cb = func(ctx context.Context) (solver.CachedResult, error) {
res, err := b.loadResult(ctx, req.Definition, req.CacheImports)
var ee *llberrdefs.ExecError
if errors.As(err, &ee) {
ee.EachRef(func(res solver.Result) error {
rp.errResults = append(rp.errResults, res)
return nil
})
}
return res, err
}
return rp
} }
func (rp *resultProxy) Definition() *pb.Definition { func (rp *resultProxy) Definition() *pb.Definition {
return rp.def return rp.def
} }
func (rp *resultProxy) Release(ctx context.Context) error { func (rp *resultProxy) Release(ctx context.Context) (err error) {
rp.mu.Lock() rp.mu.Lock()
defer rp.mu.Unlock() defer rp.mu.Unlock()
for _, res := range rp.errResults {
rerr := res.Release(ctx)
if rerr != nil {
err = rerr
}
}
if rp.v != nil { if rp.v != nil {
if rp.released { if rp.released {
logrus.Warnf("release of already released result") logrus.Warnf("release of already released result")
} }
if err := rp.v.Release(ctx); err != nil { rerr := rp.v.Release(ctx)
return err if err != nil {
return rerr
} }
} }
rp.released = true rp.released = true
return nil return
} }
func (rp *resultProxy) wrapError(err error) error { func (rp *resultProxy) wrapError(err error) error {

View File

@ -16,7 +16,6 @@ import (
"github.com/moby/buildkit/frontend/gateway" "github.com/moby/buildkit/frontend/gateway"
"github.com/moby/buildkit/session" "github.com/moby/buildkit/session"
"github.com/moby/buildkit/solver" "github.com/moby/buildkit/solver"
"github.com/moby/buildkit/solver/llbsolver/errdefs"
"github.com/moby/buildkit/util/compression" "github.com/moby/buildkit/util/compression"
"github.com/moby/buildkit/util/entitlements" "github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/progress" "github.com/moby/buildkit/util/progress"
@ -143,20 +142,6 @@ func (s *Solver) Solve(ctx context.Context, id string, sessionID string, req fro
res.EachRef(func(ref solver.ResultProxy) error { res.EachRef(func(ref solver.ResultProxy) error {
eg.Go(func() error { eg.Go(func() error {
_, err := ref.Result(ctx2) _, err := ref.Result(ctx2)
if err != nil {
// Also release any results referenced by exec errors.
var ee *errdefs.ExecError
if errors.As(err, &ee) {
ee.EachRef(func(res solver.Result) error {
workerRef, ok := res.Sys().(*worker.WorkerRef)
if !ok {
return nil
}
return workerRef.ImmutableRef.Release(ctx)
})
}
}
return err return err
}) })
return nil return nil