func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) { active := d.activeContainers[c.ID] if active == nil { return -1, fmt.Errorf("No active container exists with ID %s", c.ID) } p := &libcontainer.Process{ Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...), Env: c.ProcessConfig.Env, Cwd: c.WorkingDir, User: processConfig.User, } if processConfig.Privileged { p.Capabilities = execdriver.GetAllCapabilities() } config := active.Config() if err := setupPipes(&config, processConfig, p, pipes); err != nil { return -1, err } if err := active.Start(p); err != nil { return -1, err } if startCallback != nil { pid, err := p.Pid() if err != nil { p.Signal(os.Kill) p.Wait() return -1, err } startCallback(&c.ProcessConfig, pid) } ps, err := p.Wait() if err != nil { exitErr, ok := err.(*exec.ExitError) if !ok { return -1, err } ps = exitErr.ProcessState } return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil }
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) { // take the Command and populate the libcontainer.Config from it container, err := d.createContainer(c) if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } p := &libcontainer.Process{ Args: append([]string{c.ProcessConfig.Entrypoint}, c.ProcessConfig.Arguments...), Env: c.ProcessConfig.Env, Cwd: c.WorkingDir, User: c.ProcessConfig.User, } if err := setupPipes(container, &c.ProcessConfig, p, pipes); err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } cont, err := d.factory.Create(c.ID, container) if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } d.Lock() d.activeContainers[c.ID] = cont d.Unlock() defer func() { cont.Destroy() d.cleanContainer(c.ID) }() if err := cont.Start(p); err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } if startCallback != nil { pid, err := p.Pid() if err != nil { p.Signal(os.Kill) p.Wait() return execdriver.ExitStatus{ExitCode: -1}, err } startCallback(&c.ProcessConfig, pid) } oom := notifyOnOOM(cont) waitF := p.Wait if nss := cont.Config().Namespaces; !nss.Contains(configs.NEWPID) { // we need such hack for tracking processes with inherited fds, // because cmd.Wait() waiting for all streams to be copied waitF = waitInPIDHost(p, cont) } ps, err := waitF() if err != nil { execErr, ok := err.(*exec.ExitError) if !ok { return execdriver.ExitStatus{ExitCode: -1}, err } ps = execErr.ProcessState } cont.Destroy() _, oomKill := <-oom return execdriver.ExitStatus{ExitCode: utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), OOMKilled: oomKill}, nil }
func execAction(context *cli.Context) { factory, err := loadFactory(context) if err != nil { fatal(err) } config, err := loadConfig(context) if err != nil { fatal(err) } created := false container, err := factory.Load(context.String("id")) if err != nil { created = true if container, err = factory.Create(context.String("id"), config); err != nil { fatal(err) } } process := &libcontainer.Process{ Args: context.Args(), Env: context.StringSlice("env"), User: context.String("user"), Cwd: context.String("cwd"), Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr, } rootuid, err := config.HostUID() if err != nil { fatal(err) } tty, err := newTty(context, process, rootuid) if err != nil { fatal(err) } if err := tty.attach(process); err != nil { fatal(err) } go handleSignals(process, tty) err = container.Start(process) if err != nil { tty.Close() if created { container.Destroy() } fatal(err) } status, err := process.Wait() if err != nil { exitError, ok := err.(*exec.ExitError) if ok { status = exitError.ProcessState } else { tty.Close() if created { container.Destroy() } fatal(err) } } if created { status, err := container.Status() if err != nil { tty.Close() fatal(err) } if status != libcontainer.Checkpointed { if err := container.Destroy(); err != nil { tty.Close() fatal(err) } } } tty.Close() os.Exit(utils.ExitStatus(status.Sys().(syscall.WaitStatus))) }
exitError, ok := err.(*exec.ExitError) if ok { status = exitError.ProcessState } else { tty.Close() if created { container.Destroy() } fatal(err) } } if created { status, err := container.Status() if err != nil { tty.Close() fatal(err) } if status != libcontainer.Checkpointed { if err := container.Destroy(); err != nil { tty.Close() fatal(err) } } } tty.Close() os.Exit(utils.ExitStatus(status.Sys().(syscall.WaitStatus))) }, }
func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (execdriver.ExitStatus, error) { // take the Command and populate the libcontainer.Config from it container, err := d.createContainer(c) if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } var term execdriver.Terminal p := &libcontainer.Process{ Args: append([]string{c.ProcessConfig.Entrypoint}, c.ProcessConfig.Arguments...), Env: c.ProcessConfig.Env, Cwd: c.WorkingDir, User: c.ProcessConfig.User, } if c.ProcessConfig.Tty { rootuid, err := container.HostUID() if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } cons, err := p.NewConsole(rootuid) if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } term, err = NewTtyConsole(cons, pipes, rootuid) } else { p.Stdout = pipes.Stdout p.Stderr = pipes.Stderr r, w, err := os.Pipe() if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } if pipes.Stdin != nil { go func() { io.Copy(w, pipes.Stdin) w.Close() }() p.Stdin = r } term = &execdriver.StdConsole{} } if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } c.ProcessConfig.Terminal = term cont, err := d.factory.Create(c.ID, container) if err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } d.Lock() d.activeContainers[c.ID] = cont d.Unlock() defer func() { cont.Destroy() d.cleanContainer(c.ID) }() if err := cont.Start(p); err != nil { return execdriver.ExitStatus{ExitCode: -1}, err } if startCallback != nil { pid, err := p.Pid() if err != nil { p.Signal(os.Kill) p.Wait() return execdriver.ExitStatus{ExitCode: -1}, err } startCallback(&c.ProcessConfig, pid) } oomKillNotification, err := cont.NotifyOOM() if err != nil { oomKillNotification = nil log.Warnf("Your kernel does not support OOM notifications: %s", err) } waitF := p.Wait if nss := cont.Config().Namespaces; nss.Contains(configs.NEWPID) { // we need such hack for tracking processes with inerited fds, // because cmd.Wait() waiting for all streams to be copied waitF = waitInPIDHost(p, cont) } ps, err := waitF() if err != nil { if err, ok := err.(*exec.ExitError); !ok { return execdriver.ExitStatus{ExitCode: -1}, err } else { ps = err.ProcessState } } cont.Destroy() _, oomKill := <-oomKillNotification return execdriver.ExitStatus{ExitCode: utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), OOMKilled: oomKill}, nil }
func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) { active := d.activeContainers[c.ID] if active == nil { return -1, fmt.Errorf("No active container exists with ID %s", c.ID) } var term execdriver.Terminal var err error p := &libcontainer.Process{ Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...), Env: c.ProcessConfig.Env, Cwd: c.WorkingDir, User: processConfig.User, } if processConfig.Privileged { p.Capabilities = execdriver.GetAllCapabilities() } if processConfig.Tty { config := active.Config() rootuid, err := config.HostUID() if err != nil { return -1, err } cons, err := p.NewConsole(rootuid) if err != nil { return -1, err } term, err = NewTtyConsole(cons, pipes, rootuid) } else { p.Stdout = pipes.Stdout p.Stderr = pipes.Stderr p.Stdin = pipes.Stdin term = &execdriver.StdConsole{} } if err != nil { return -1, err } processConfig.Terminal = term if err := active.Start(p); err != nil { return -1, err } if startCallback != nil { pid, err := p.Pid() if err != nil { p.Signal(os.Kill) p.Wait() return -1, err } startCallback(&c.ProcessConfig, pid) } ps, err := p.Wait() if err != nil { exitErr, ok := err.(*exec.ExitError) if !ok { return -1, err } ps = exitErr.ProcessState } return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil }