// +build linux solaris package libcontainerd import ( "io" "io/ioutil" "os" "path/filepath" goruntime "runtime" "time" containerd "github.com/docker/containerd/api/grpc/types" "github.com/tonistiigi/fifo" "golang.org/x/net/context" "golang.org/x/sys/unix" ) var fdNames = map[int]string{ unix.Stdin: "stdin", unix.Stdout: "stdout", unix.Stderr: "stderr", } // process keeps the state for both main container process and exec process. type process struct { processCommon // Platform specific fields are below here. dir string } func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) { if err := os.MkdirAll(p.dir, 0700); err != nil { return nil, err } ctx, _ := context.WithTimeout(context.Background(), 15*time.Second) io := &IOPipe{} io.Stdin, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdin), unix.O_WRONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700) if err != nil { return nil, err } defer func() { if err != nil { io.Stdin.Close() } }() io.Stdout, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdout), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700) if err != nil { return nil, err } defer func() { if err != nil { io.Stdout.Close() } }() if goruntime.GOOS == "solaris" || !terminal { // For Solaris terminal handling is done exclusively by the runtime therefore we make no distinction // in the processing for terminal and !terminal cases. io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(unix.Stderr), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700) if err != nil { return nil, err } defer func() { if err != nil { io.Stderr.Close() } }() } else { io.Stderr = ioutil.NopCloser(emptyReader{}) } return io, nil } func (p *process) sendCloseStdin() error { _, err := p.client.remote.apiClient.UpdateProcess(context.Background(), &containerd.UpdateProcessRequest{ Id: p.containerID, Pid: p.friendlyName, CloseStdin: true, }) return err } func (p *process) closeFifos(io *IOPipe) { io.Stdin.Close() io.Stdout.Close() io.Stderr.Close() } type emptyReader struct{} func (r emptyReader) Read(b []byte) (int, error) { return 0, io.EOF } func (p *process) fifo(index int) string { return filepath.Join(p.dir, p.friendlyName+"-"+fdNames[index]) }