func Apply(c *cgroups.Cgroup, pid int) (map[string]string, error) { d, err := getCgroupData(c, pid) if err != nil { return nil, err } paths := make(map[string]string) defer func() { if err != nil { cgroups.RemovePaths(paths) } }() for name, sys := range subsystems { if err := sys.Set(d); err != nil { return nil, err } // FIXME: Apply should, ideally, be reentrant or be broken up into a separate // create and join phase so that the cgroup hierarchy for a container can be // created then join consists of writing the process pids to cgroup.procs p, err := d.path(name) if err != nil { if cgroups.IsNotFound(err) { continue } return nil, err } paths[name] = p } return paths, nil }
func (m *Manager) Destroy() error { m.mu.Lock() defer m.mu.Unlock() if err := cgroups.RemovePaths(m.Paths); err != nil { return err } m.Paths = make(map[string]string) return nil }
func (m *Manager) Destroy() error { m.mu.Lock() defer m.mu.Unlock() theConn.StopUnit(getUnitName(m.Cgroups), "replace") if err := cgroups.RemovePaths(m.Paths); err != nil { return err } m.Paths = make(map[string]string) return nil }
func (m *Manager) Apply(pid int) error { if m.Cgroups == nil { return nil } var c = m.Cgroups d, err := getCgroupData(m.Cgroups, pid) if err != nil { return err } paths := make(map[string]string) defer func() { if err != nil { cgroups.RemovePaths(paths) } }() for name, sys := range subsystems { if err := sys.Apply(d); err != nil { return err } // TODO: Apply should, ideally, be reentrant or be broken up into a separate // create and join phase so that the cgroup hierarchy for a container can be // created then join consists of writing the process pids to cgroup.procs p, err := d.path(name) if err != nil { if cgroups.IsNotFound(err) { continue } return err } paths[name] = p } m.Paths = paths if paths["cpu"] != "" { if err := CheckCpushares(paths["cpu"], c.CpuShares); err != nil { return err } } return nil }
func (m *Manager) Destroy() error { return cgroups.RemovePaths(m.Paths) }
// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work. // Move this to libcontainer package. // Exec performs setup outside of a namespace so that a container can be // executed. Exec is a high level function for working with container namespaces. func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Writer, console, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) { var err error // create a pipe so that we can syncronize with the namespaced process and // pass the state and configuration to the child process parent, child, err := newInitPipe() if err != nil { return -1, err } defer parent.Close() command := createCommand(container, console, dataPath, os.Args[0], child, args) // Note: these are only used in non-tty mode // if there is a tty for the container it will be opened within the namespace and the // fds will be duped to stdin, stdiout, and stderr command.Stdin = stdin command.Stdout = stdout command.Stderr = stderr if err := command.Start(); err != nil { child.Close() return -1, err } child.Close() wait := func() (*os.ProcessState, error) { ps, err := command.Process.Wait() // we should kill all processes in cgroup when init is died if we use // host PID namespace if !container.Namespaces.Contains(libcontainer.NEWPID) { killAllPids(container) } return ps, err } terminate := func(terr error) (int, error) { // TODO: log the errors for kill and wait command.Process.Kill() wait() return -1, terr } started, err := system.GetProcessStartTime(command.Process.Pid) if err != nil { return terminate(err) } // Do this before syncing with child so that no children // can escape the cgroup cgroupPaths, err := SetupCgroups(container, command.Process.Pid) if err != nil { return terminate(err) } defer cgroups.RemovePaths(cgroupPaths) var networkState network.NetworkState if err := InitializeNetworking(container, command.Process.Pid, &networkState); err != nil { return terminate(err) } // send the state to the container's init process then shutdown writes for the parent if err := json.NewEncoder(parent).Encode(networkState); err != nil { return terminate(err) } // shutdown writes for the parent side of the pipe if err := syscall.Shutdown(int(parent.Fd()), syscall.SHUT_WR); err != nil { return terminate(err) } state := &libcontainer.State{ InitPid: command.Process.Pid, InitStartTime: started, NetworkState: networkState, CgroupPaths: cgroupPaths, } if err := libcontainer.SaveState(dataPath, state); err != nil { return terminate(err) } defer libcontainer.DeleteState(dataPath) // wait for the child process to fully complete and receive an error message // if one was encoutered var ierr *initError if err := json.NewDecoder(parent).Decode(&ierr); err != nil && err != io.EOF { return terminate(err) } if ierr != nil { return terminate(ierr) } if startCallback != nil { startCallback() } ps, err := wait() if err != nil { if _, ok := err.(*exec.ExitError); !ok { return -1, err } } // waiting for pipe flushing command.Wait() waitStatus := ps.Sys().(syscall.WaitStatus) if waitStatus.Signaled() { return EXIT_SIGNAL_OFFSET + int(waitStatus.Signal()), nil } return waitStatus.ExitStatus(), nil }