Merge pull request #430 from crosbymichael/pipes

Move STDIO initialization to libcontainer.Process
This commit is contained in:
Mrunal Patel 2015-12-11 14:30:42 -08:00
commit 11f8fdca33
5 changed files with 62 additions and 44 deletions

View File

@ -5,6 +5,7 @@ import (
"io"
"math"
"os"
"syscall"
)
type processOperations interface {
@ -78,6 +79,54 @@ func (p Process) Signal(sig os.Signal) error {
return p.ops.signal(sig)
}
// IO holds the process's STDIO
type IO struct {
Stdin io.WriteCloser
Stdout io.ReadCloser
Stderr io.ReadCloser
}
// InitializeIO creates pipes for use with the process's STDIO
// and returns the opposite side for each
func (p *Process) InitializeIO(rootuid int) (i *IO, err error) {
var fds []uintptr
i = &IO{}
// cleanup in case of an error
defer func() {
if err != nil {
for _, fd := range fds {
syscall.Close(int(fd))
}
}
}()
// STDIN
r, w, err := os.Pipe()
if err != nil {
return nil, err
}
fds = append(fds, r.Fd(), w.Fd())
p.Stdin, i.Stdin = r, w
// STDOUT
if r, w, err = os.Pipe(); err != nil {
return nil, err
}
fds = append(fds, r.Fd(), w.Fd())
p.Stdout, i.Stdout = w, r
// STDERR
if r, w, err = os.Pipe(); err != nil {
return nil, err
}
fds = append(fds, r.Fd(), w.Fd())
p.Stderr, i.Stderr = w, r
// change ownership of the pipes incase we are in a user namespace
for _, fd := range fds {
if err := syscall.Fchown(int(fd), rootuid, rootuid); err != nil {
return nil, err
}
}
return i, nil
}
// NewConsole creates new console for process and returns it
func (p *Process) NewConsole(rootuid int) (Console, error) {
console, err := NewConsole(rootuid, rootuid)

View File

@ -126,11 +126,7 @@ func restoreContainer(context *cli.Context, spec *specs.LinuxSpec, config *confi
}
}
}()
process := &libcontainer.Process{
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
}
process := &libcontainer.Process{}
tty, err := newTty(spec.Process.Terminal, process, rootuid)
if err != nil {
return -1, err

View File

@ -110,12 +110,10 @@ func startContainer(context *cli.Context, spec *specs.LinuxSpec, rspec *specs.Li
if err != nil {
return -1, err
}
for i := SD_LISTEN_FDS_START; i < (listenFdsInt + SD_LISTEN_FDS_START); i++ {
process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), ""))
}
}
tty, err := newTty(spec.Process.Terminal, process, rootuid)
if err != nil {
return -1, err

42
tty.go
View File

@ -6,7 +6,6 @@ import (
"fmt"
"io"
"os"
"syscall"
"github.com/docker/docker/pkg/term"
"github.com/opencontainers/runc/libcontainer"
@ -25,38 +24,20 @@ func newTty(create bool, p *libcontainer.Process, rootuid int) (*tty, error) {
// setup standard pipes so that the TTY of the calling runc process
// is not inherited by the container.
func createStdioPipes(p *libcontainer.Process, rootuid int) (*tty, error) {
var (
t = &tty{}
fds []int
)
r, w, err := os.Pipe()
i, err := p.InitializeIO(rootuid)
if err != nil {
return nil, err
}
fds = append(fds, int(r.Fd()), int(w.Fd()))
go io.Copy(w, os.Stdin)
t.closers = append(t.closers, w)
p.Stdin = r
if r, w, err = os.Pipe(); err != nil {
return nil, err
}
fds = append(fds, int(r.Fd()), int(w.Fd()))
go io.Copy(os.Stdout, r)
p.Stdout = w
t.closers = append(t.closers, r)
if r, w, err = os.Pipe(); err != nil {
return nil, err
}
fds = append(fds, int(r.Fd()), int(w.Fd()))
go io.Copy(os.Stderr, r)
p.Stderr = w
t.closers = append(t.closers, r)
// change the ownership of the pipe fds incase we are in a user namespace.
for _, fd := range fds {
if err := syscall.Fchown(fd, rootuid, rootuid); err != nil {
return nil, err
}
t := &tty{
closers: []io.Closer{
i.Stdin,
i.Stdout,
i.Stderr,
},
}
go io.Copy(i.Stdin, os.Stdin)
go io.Copy(os.Stdout, i.Stdout)
go io.Copy(os.Stderr, i.Stderr)
return t, nil
}
@ -78,9 +59,6 @@ func createTty(p *libcontainer.Process, rootuid int) (*tty, error) {
console,
},
}
p.Stderr = nil
p.Stdout = nil
p.Stdin = nil
return t, nil
}

View File

@ -161,10 +161,7 @@ func newProcess(p specs.Process) *libcontainer.Process {
Args: p.Args,
Env: p.Env,
// TODO: fix libcontainer's API to better support uid/gid in a typesafe way.
User: fmt.Sprintf("%d:%d", p.User.UID, p.User.GID),
Cwd: p.Cwd,
Stdin: os.Stdin,
Stdout: os.Stdout,
Stderr: os.Stderr,
User: fmt.Sprintf("%d:%d", p.User.UID, p.User.GID),
Cwd: p.Cwd,
}
}