Skip to content

Commit

Permalink
integration: detect double released and leaked mountpoints
Browse files Browse the repository at this point in the history
Signed-off-by: Tonis Tiigi <[email protected]>
  • Loading branch information
tonistiigi committed Aug 16, 2019
1 parent a0dead0 commit b828430
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
20 changes: 16 additions & 4 deletions snapshot/snapshotter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package snapshot

import (
"context"
"os"
"sync"
"sync/atomic"

"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/snapshots"
Expand Down Expand Up @@ -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...)
Expand All @@ -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 {
Expand Down
25 changes: 24 additions & 1 deletion util/testutil/integration/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"runtime"
"strings"
"syscall"
"testing"
"time"
Expand Down Expand Up @@ -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")
Expand All @@ -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
}
Expand All @@ -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
}

Expand Down

0 comments on commit b828430

Please sign in to comment.