diff --git a/project/vendor.sh b/project/vendor.sh index d15d261714..b60e42f5c4 100755 --- a/project/vendor.sh +++ b/project/vendor.sh @@ -68,7 +68,7 @@ if [ "$1" = '--go' ]; then mv tmp-tar src/code.google.com/p/go/src/pkg/archive/tar fi -clone git github.com/docker/libcontainer 1d3b2589d734dc94a1719a3af40b87ed8319f329 +clone git github.com/docker/libcontainer eb74393a3d2daeafbef4f5f27c0821cbdd67559c # see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file) rm -rf src/github.com/docker/libcontainer/vendor eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli')" diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go index f05377f25b..58046b0ad7 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go @@ -124,11 +124,17 @@ func Freeze(c *cgroups.Cgroup, state cgroups.FreezerState) error { return err } + prevState := c.Freezer c.Freezer = state freezer := subsystems["freezer"] + err = freezer.Set(d) + if err != nil { + c.Freezer = prevState + return err + } - return freezer.Set(d) + return nil } func GetPids(c *cgroups.Cgroup) ([]int, error) { diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/execin.go b/vendor/src/github.com/docker/libcontainer/namespaces/execin.go index 7ce82c81bb..ddff5c3a9f 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/execin.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/execin.go @@ -73,6 +73,11 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs return terminate(err) } + // finish cgroups' setup, unblock the child process. + if _, err := parent.WriteString("1"); err != nil { + return terminate(err) + } + if err := json.NewEncoder(parent).Encode(container); err != nil { return terminate(err) } diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter.c b/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter.c index 9782702dcd..4ab21774fb 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter.c +++ b/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter.c @@ -28,7 +28,6 @@ void get_args(int *argc, char ***argv) pr_perror("Unable to open /proc/self/cmdline"); exit(1); } - // Read the whole commandline. ssize_t contents_size = 0; ssize_t contents_offset = 0; @@ -98,13 +97,12 @@ void nsenter() if (strncmp(argv[0], kNsEnter, strlen(kNsEnter)) != 0) { return; } - - #ifdef PR_SET_CHILD_SUBREAPER +#ifdef PR_SET_CHILD_SUBREAPER if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0) == -1) { pr_perror("Failed to set child subreaper"); exit(1); } - #endif +#endif static const struct option longopts[] = { {"nspid", required_argument, NULL, 'n'}, @@ -134,7 +132,7 @@ void nsenter() init_pid = strtol(init_pid_str, NULL, 10); if ((init_pid == 0 && errno == EINVAL) || errno == ERANGE) { pr_perror("Failed to parse PID from \"%s\" with output \"%d\"", - init_pid_str, init_pid); + init_pid_str, init_pid); print_usage(); exit(1); } @@ -155,6 +153,12 @@ void nsenter() exit(1); } } + // blocking until the parent placed the process inside correct cgroups. + unsigned char s; + if (read(3, &s, 1) != 1 || s != '1') { + pr_perror("failed to receive synchronization data from parent"); + exit(1); + } // Setns on all supported namespaces. char ns_dir[PATH_MAX]; memset(ns_dir, 0, PATH_MAX); @@ -173,18 +177,19 @@ void nsenter() for (i = 0; i < num; i++) { // A zombie process has links on namespaces, but they can't be opened struct stat st; - if (fstatat(ns_dir_fd, namespaces[i], &st, AT_SYMLINK_NOFOLLOW) == -1) { + if (fstatat(ns_dir_fd, namespaces[i], &st, AT_SYMLINK_NOFOLLOW) + == -1) { if (errno == ENOENT) continue; pr_perror("Failed to stat ns file %s for ns %s", - ns_dir, namespaces[i]); + ns_dir, namespaces[i]); exit(1); } int fd = openat(ns_dir_fd, namespaces[i], O_RDONLY); if (fd == -1) { pr_perror("Failed to open ns file %s for ns %s", - ns_dir, namespaces[i]); + ns_dir, namespaces[i]); exit(1); } // Set the namespace. diff --git a/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter_test.go b/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter_test.go index 85ee5d6725..14870c457e 100644 --- a/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter_test.go +++ b/vendor/src/github.com/docker/libcontainer/namespaces/nsenter/nsenter_test.go @@ -12,15 +12,29 @@ import ( func TestNsenterAlivePid(t *testing.T) { args := []string{"nsenter-exec", "--nspid", fmt.Sprintf("%d", os.Getpid())} - - cmd := &exec.Cmd{ - Path: os.Args[0], - Args: args, + r, w, err := os.Pipe() + if err != nil { + t.Fatalf("failed to create pipe %v", err) } - err := cmd.Run() - if err != nil { - t.Fatal("nsenter exits with a non-zero exit status") + cmd := &exec.Cmd{ + Path: os.Args[0], + Args: args, + ExtraFiles: []*os.File{r}, + } + + if err := cmd.Start(); err != nil { + t.Fatalf("nsenter failed to start %v", err) + } + r.Close() + + // unblock the child process + if _, err := w.WriteString("1"); err != nil { + t.Fatalf("parent failed to write synchronization data %v", err) + } + + if err := cmd.Wait(); err != nil { + t.Fatalf("nsenter exits with a non-zero exit status") } }