github.com/akerouanton/docker@v1.11.0-rc3/libcontainerd/process_linux.go (about) 1 package libcontainerd 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 "syscall" 9 10 containerd "github.com/docker/containerd/api/grpc/types" 11 "github.com/docker/docker/pkg/ioutils" 12 "golang.org/x/net/context" 13 ) 14 15 var fdNames = map[int]string{ 16 syscall.Stdin: "stdin", 17 syscall.Stdout: "stdout", 18 syscall.Stderr: "stderr", 19 } 20 21 // process keeps the state for both main container process and exec process. 22 type process struct { 23 processCommon 24 25 // Platform specific fields are below here. 26 dir string 27 } 28 29 func (p *process) openFifos(terminal bool) (*IOPipe, error) { 30 bundleDir := p.dir 31 if err := os.MkdirAll(bundleDir, 0700); err != nil { 32 return nil, err 33 } 34 35 for i := 0; i < 3; i++ { 36 f := p.fifo(i) 37 if err := syscall.Mkfifo(f, 0700); err != nil && !os.IsExist(err) { 38 return nil, fmt.Errorf("mkfifo: %s %v", f, err) 39 } 40 } 41 42 io := &IOPipe{} 43 stdinf, err := os.OpenFile(p.fifo(syscall.Stdin), syscall.O_RDWR, 0) 44 if err != nil { 45 return nil, err 46 } 47 48 io.Stdout = openReaderFromFifo(p.fifo(syscall.Stdout)) 49 if !terminal { 50 io.Stderr = openReaderFromFifo(p.fifo(syscall.Stderr)) 51 } else { 52 io.Stderr = emptyReader{} 53 } 54 55 io.Stdin = ioutils.NewWriteCloserWrapper(stdinf, func() error { 56 stdinf.Close() 57 _, err := p.client.remote.apiClient.UpdateProcess(context.Background(), &containerd.UpdateProcessRequest{ 58 Id: p.containerID, 59 Pid: p.friendlyName, 60 CloseStdin: true, 61 }) 62 return err 63 }) 64 65 return io, nil 66 } 67 68 func (p *process) closeFifos(io *IOPipe) { 69 io.Stdin.Close() 70 closeReaderFifo(p.fifo(syscall.Stdout)) 71 closeReaderFifo(p.fifo(syscall.Stderr)) 72 } 73 74 type emptyReader struct{} 75 76 func (r emptyReader) Read(b []byte) (int, error) { 77 return 0, io.EOF 78 } 79 80 func openReaderFromFifo(fn string) io.Reader { 81 r, w := io.Pipe() 82 go func() { 83 stdoutf, err := os.OpenFile(fn, syscall.O_RDONLY, 0) 84 if err != nil { 85 r.CloseWithError(err) 86 } 87 if _, err := io.Copy(w, stdoutf); err != nil { 88 r.CloseWithError(err) 89 } 90 w.Close() 91 stdoutf.Close() 92 }() 93 return r 94 } 95 96 // closeReaderFifo closes fifo that may be blocked on open by opening the write side. 97 func closeReaderFifo(fn string) { 98 f, err := os.OpenFile(fn, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) 99 if err != nil { 100 return 101 } 102 f.Close() 103 } 104 105 func (p *process) fifo(index int) string { 106 return filepath.Join(p.dir, p.friendlyName+"-"+fdNames[index]) 107 }