integration: detect double released and leaked mountpoints
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>docker-19.03
parent
a0dead0809
commit
b8284301fd
|
@ -2,7 +2,9 @@ package snapshot
|
|||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
|
@ -62,7 +64,7 @@ func (s *fromContainerd) Mounts(ctx context.Context, key string) (Mountable, err
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &staticMountable{mounts, s.idmap}, nil
|
||||
return &staticMountable{mounts: mounts, idmap: s.idmap, id: key}, nil
|
||||
}
|
||||
func (s *fromContainerd) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) error {
|
||||
_, err := s.Snapshotter.Prepare(ctx, key, parent, opts...)
|
||||
|
@ -73,19 +75,29 @@ func (s *fromContainerd) View(ctx context.Context, key, parent string, opts ...s
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &staticMountable{mounts, s.idmap}, nil
|
||||
return &staticMountable{mounts: mounts, idmap: s.idmap, id: key}, nil
|
||||
}
|
||||
func (s *fromContainerd) IdentityMapping() *idtools.IdentityMapping {
|
||||
return s.idmap
|
||||
}
|
||||
|
||||
type staticMountable struct {
|
||||
count int32
|
||||
id string
|
||||
mounts []mount.Mount
|
||||
idmap *idtools.IdentityMapping
|
||||
}
|
||||
|
||||
func (m *staticMountable) Mount() ([]mount.Mount, func() error, error) {
|
||||
return m.mounts, func() error { return nil }, nil
|
||||
func (cm *staticMountable) Mount() ([]mount.Mount, func() error, error) {
|
||||
atomic.AddInt32(&cm.count, 1)
|
||||
return cm.mounts, func() error {
|
||||
if atomic.AddInt32(&cm.count, -1) < 0 {
|
||||
if v := os.Getenv("BUILDKIT_DEBUG_PANIC_ON_ERROR"); v == "1" {
|
||||
panic("release of released mount " + cm.id)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cm *staticMountable) IdentityMapping() *idtools.IdentityMapping {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -181,6 +182,13 @@ func runBuildkitd(args []string, logs map[string]*bytes.Buffer, uid, gid int) (a
|
|||
if err := os.Chown(tmpdir, uid, gid); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Join(tmpdir, "tmp"), 0711); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if err := os.Chown(filepath.Join(tmpdir, "tmp"), uid, gid); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
deferF.append(func() error { return os.RemoveAll(tmpdir) })
|
||||
|
||||
address = "unix://" + filepath.Join(tmpdir, "buildkitd.sock")
|
||||
|
@ -190,7 +198,7 @@ func runBuildkitd(args []string, logs map[string]*bytes.Buffer, uid, gid int) (a
|
|||
|
||||
args = append(args, "--root", tmpdir, "--addr", address, "--debug")
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
cmd.Env = append(os.Environ(), "BUILDKIT_DEBUG_EXEC_OUTPUT=1")
|
||||
cmd.Env = append(os.Environ(), "BUILDKIT_DEBUG_EXEC_OUTPUT=1", "BUILDKIT_DEBUG_PANIC_ON_ERROR=1", "TMPDIR="+filepath.Join(tmpdir, "tmp"))
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setsid: true, // stretch sudo needs this for sigterm
|
||||
}
|
||||
|
@ -205,6 +213,21 @@ func runBuildkitd(args []string, logs map[string]*bytes.Buffer, uid, gid int) (a
|
|||
return "", nil, err
|
||||
}
|
||||
|
||||
deferF.append(func() error {
|
||||
f, err := os.Open("/proc/self/mountinfo")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to open mountinfo")
|
||||
}
|
||||
defer f.Close()
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
if strings.Contains(s.Text(), tmpdir) {
|
||||
return errors.Errorf("leaked mountpoint for %s", tmpdir)
|
||||
}
|
||||
}
|
||||
return s.Err()
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue