mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Refactor exec method
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
This commit is contained in:
parent
5a4069f3aa
commit
dd59f7fb28
1 changed files with 77 additions and 61 deletions
|
@ -22,20 +22,10 @@ import (
|
||||||
func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.Writer,
|
func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.Writer,
|
||||||
master *os.File, logFile string, args []string) (int, error) {
|
master *os.File, logFile string, args []string) (int, error) {
|
||||||
var (
|
var (
|
||||||
console string
|
console string
|
||||||
err error
|
err error
|
||||||
inPipe io.WriteCloser
|
|
||||||
outPipe, errPipe io.ReadCloser
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if container.Tty {
|
|
||||||
log.Printf("setting up master and console")
|
|
||||||
master, console, err = CreateMasterAndConsole()
|
|
||||||
if err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a pipe so that we can syncronize with the namespaced process and
|
// create a pipe so that we can syncronize with the namespaced process and
|
||||||
// pass the veth name to the child
|
// pass the veth name to the child
|
||||||
r, w, err := os.Pipe()
|
r, w, err := os.Pipe()
|
||||||
|
@ -44,49 +34,15 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
|
||||||
}
|
}
|
||||||
system.UsetCloseOnExec(r.Fd())
|
system.UsetCloseOnExec(r.Fd())
|
||||||
|
|
||||||
|
if container.Tty {
|
||||||
|
log.Printf("setting up master and console")
|
||||||
|
master, console, err = CreateMasterAndConsole()
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
command := CreateCommand(container, console, logFile, r.Fd(), args)
|
command := CreateCommand(container, console, logFile, r.Fd(), args)
|
||||||
if !container.Tty {
|
|
||||||
log.Printf("opening std pipes")
|
|
||||||
if inPipe, err = command.StdinPipe(); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
if outPipe, err = command.StdoutPipe(); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
if errPipe, err = command.StderrPipe(); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("staring init")
|
|
||||||
if err := command.Start(); err != nil {
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
log.Printf("writting state file")
|
|
||||||
if err := writePidFile(command); err != nil {
|
|
||||||
command.Process.Kill()
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
defer deletePidFile()
|
|
||||||
|
|
||||||
// Do this before syncing with child so that no children
|
|
||||||
// can escape the cgroup
|
|
||||||
if container.Cgroups != nil {
|
|
||||||
log.Printf("setting up cgroups")
|
|
||||||
if err := container.Cgroups.Apply(command.Process.Pid); err != nil {
|
|
||||||
command.Process.Kill()
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := InitializeNetworking(container, command.Process.Pid, w); err != nil {
|
|
||||||
command.Process.Kill()
|
|
||||||
return -1, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync with child
|
|
||||||
log.Printf("closing sync pipes")
|
|
||||||
w.Close()
|
|
||||||
r.Close()
|
|
||||||
|
|
||||||
if container.Tty {
|
if container.Tty {
|
||||||
log.Printf("starting copy for tty")
|
log.Printf("starting copy for tty")
|
||||||
|
@ -100,15 +56,39 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
|
||||||
}
|
}
|
||||||
defer term.RestoreTerminal(os.Stdin.Fd(), state)
|
defer term.RestoreTerminal(os.Stdin.Fd(), state)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("starting copy for std pipes")
|
if err := startStdCopy(command, stdin, stdout, stderr); err != nil {
|
||||||
go func() {
|
command.Process.Kill()
|
||||||
defer inPipe.Close()
|
return -1, err
|
||||||
io.Copy(inPipe, stdin)
|
}
|
||||||
}()
|
|
||||||
go io.Copy(stdout, outPipe)
|
|
||||||
go io.Copy(stderr, errPipe)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("staring init")
|
||||||
|
if err := command.Start(); err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
log.Printf("writing state file")
|
||||||
|
if err := writePidFile(command); err != nil {
|
||||||
|
command.Process.Kill()
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
defer deletePidFile()
|
||||||
|
|
||||||
|
// Do this before syncing with child so that no children
|
||||||
|
// can escape the cgroup
|
||||||
|
if err := SetupCgroups(container, command.Process.Pid); err != nil {
|
||||||
|
command.Process.Kill()
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
if err := InitializeNetworking(container, command.Process.Pid, w); err != nil {
|
||||||
|
command.Process.Kill()
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync with child
|
||||||
|
log.Printf("closing sync pipes")
|
||||||
|
w.Close()
|
||||||
|
r.Close()
|
||||||
|
|
||||||
log.Printf("waiting on process")
|
log.Printf("waiting on process")
|
||||||
if err := command.Wait(); err != nil {
|
if err := command.Wait(); err != nil {
|
||||||
if _, ok := err.(*exec.ExitError); !ok {
|
if _, ok := err.(*exec.ExitError); !ok {
|
||||||
|
@ -119,6 +99,16 @@ func Exec(container *libcontainer.Container, stdin io.Reader, stdout, stderr io.
|
||||||
return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
|
return command.ProcessState.Sys().(syscall.WaitStatus).ExitStatus(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetupCgroups(container *libcontainer.Container, nspid int) error {
|
||||||
|
if container.Cgroups != nil {
|
||||||
|
log.Printf("setting up cgroups")
|
||||||
|
if err := container.Cgroups.Apply(nspid); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func InitializeNetworking(container *libcontainer.Container, nspid int, pipe io.Writer) error {
|
func InitializeNetworking(container *libcontainer.Container, nspid int, pipe io.Writer) error {
|
||||||
if container.Network != nil {
|
if container.Network != nil {
|
||||||
log.Printf("creating host network configuration type %s", container.Network.Type)
|
log.Printf("creating host network configuration type %s", container.Network.Type)
|
||||||
|
@ -207,3 +197,29 @@ func CreateCommand(container *libcontainer.Container, console, logFile string, p
|
||||||
command.Env = container.Env
|
command.Env = container.Env
|
||||||
return command
|
return command
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startStdCopy(command *exec.Cmd, stdin io.Reader, stdout, stderr io.Writer) error {
|
||||||
|
log.Printf("opening std pipes")
|
||||||
|
inPipe, err := command.StdinPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outPipe, err := command.StdoutPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
errPipe, err := command.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("starting copy for std pipes")
|
||||||
|
go func() {
|
||||||
|
defer inPipe.Close()
|
||||||
|
io.Copy(inPipe, stdin)
|
||||||
|
}()
|
||||||
|
go io.Copy(stdout, outPipe)
|
||||||
|
go io.Copy(stderr, errPipe)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue