2020-10-28 21:07:44 +00:00
|
|
|
package errdefs
|
|
|
|
|
|
|
|
import (
|
2020-11-25 23:13:59 +00:00
|
|
|
"context"
|
|
|
|
"runtime"
|
|
|
|
|
2020-10-28 21:07:44 +00:00
|
|
|
"github.com/moby/buildkit/solver"
|
2021-07-09 07:48:03 +00:00
|
|
|
"github.com/moby/buildkit/util/bklog"
|
2020-10-28 21:07:44 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ExecError will be returned when an error is encountered when evaluating an op.
|
|
|
|
type ExecError struct {
|
|
|
|
error
|
2020-11-25 23:13:59 +00:00
|
|
|
Inputs []solver.Result
|
|
|
|
Mounts []solver.Result
|
|
|
|
OwnerBorrowed bool
|
2020-10-28 21:07:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ExecError) Unwrap() error {
|
|
|
|
return e.error
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *ExecError) EachRef(fn func(solver.Result) error) (err error) {
|
2021-02-03 18:49:48 +00:00
|
|
|
m := map[solver.Result]struct{}{}
|
2020-10-28 21:07:44 +00:00
|
|
|
for _, res := range e.Inputs {
|
2020-11-14 07:20:41 +00:00
|
|
|
if res == nil {
|
|
|
|
continue
|
|
|
|
}
|
2021-02-03 18:49:48 +00:00
|
|
|
if _, ok := m[res]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m[res] = struct{}{}
|
2020-10-28 21:07:44 +00:00
|
|
|
if err1 := fn(res); err1 != nil && err == nil {
|
|
|
|
err = err1
|
|
|
|
}
|
|
|
|
}
|
2020-11-14 07:20:41 +00:00
|
|
|
for _, res := range e.Mounts {
|
|
|
|
if res == nil {
|
|
|
|
continue
|
|
|
|
}
|
2021-02-03 18:49:48 +00:00
|
|
|
if _, ok := m[res]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
m[res] = struct{}{}
|
2020-10-28 21:07:44 +00:00
|
|
|
if err1 := fn(res); err1 != nil && err == nil {
|
|
|
|
err = err1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-25 23:13:59 +00:00
|
|
|
func (e *ExecError) Release() error {
|
|
|
|
if e.OwnerBorrowed {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
err := e.EachRef(func(r solver.Result) error {
|
|
|
|
r.Release(context.TODO())
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
e.OwnerBorrowed = true
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-14 07:20:41 +00:00
|
|
|
func WithExecError(err error, inputs, mounts []solver.Result) error {
|
2021-07-09 07:48:03 +00:00
|
|
|
return WithExecErrorWithContext(context.TODO(), err, inputs, mounts)
|
|
|
|
}
|
|
|
|
|
|
|
|
func WithExecErrorWithContext(ctx context.Context, err error, inputs, mounts []solver.Result) error {
|
2020-10-28 21:07:44 +00:00
|
|
|
if err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
2020-11-25 23:13:59 +00:00
|
|
|
ee := &ExecError{
|
2020-11-14 07:20:41 +00:00
|
|
|
error: err,
|
|
|
|
Inputs: inputs,
|
|
|
|
Mounts: mounts,
|
2020-10-28 21:07:44 +00:00
|
|
|
}
|
2020-11-25 23:13:59 +00:00
|
|
|
runtime.SetFinalizer(ee, func(e *ExecError) {
|
|
|
|
if !e.OwnerBorrowed {
|
|
|
|
e.EachRef(func(r solver.Result) error {
|
2021-07-09 07:48:03 +00:00
|
|
|
bklog.G(ctx).Warn("leaked execError detected and released")
|
2020-11-25 23:13:59 +00:00
|
|
|
r.Release(context.TODO())
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return ee
|
2020-10-28 21:07:44 +00:00
|
|
|
}
|