| package libcontainerd |
| |
| import ( |
| "io" |
| "io/ioutil" |
| "os" |
| "path/filepath" |
| "syscall" |
| "time" |
| |
| containerd "github.com/docker/containerd/api/grpc/types" |
| "github.com/tonistiigi/fifo" |
| "golang.org/x/net/context" |
| ) |
| |
| var fdNames = map[int]string{ |
| syscall.Stdin: "stdin", |
| syscall.Stdout: "stdout", |
| syscall.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(syscall.Stdin), syscall.O_WRONLY|syscall.O_CREAT|syscall.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(syscall.Stdout), syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700) |
| if err != nil { |
| return nil, err |
| } |
| |
| defer func() { |
| if err != nil { |
| io.Stdout.Close() |
| } |
| }() |
| |
| if !terminal { |
| io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stderr), syscall.O_RDONLY|syscall.O_CREAT|syscall.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]) |
| } |