process_linux.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. package libcontainerd
  2. import (
  3. "io"
  4. "io/ioutil"
  5. "os"
  6. "path/filepath"
  7. "syscall"
  8. "time"
  9. containerd "github.com/docker/containerd/api/grpc/types"
  10. "github.com/docker/docker/pkg/ioutils"
  11. "github.com/tonistiigi/fifo"
  12. "golang.org/x/net/context"
  13. )
  14. var fdNames = map[int]string{
  15. syscall.Stdin: "stdin",
  16. syscall.Stdout: "stdout",
  17. syscall.Stderr: "stderr",
  18. }
  19. // process keeps the state for both main container process and exec process.
  20. type process struct {
  21. processCommon
  22. // Platform specific fields are below here.
  23. dir string
  24. }
  25. func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) {
  26. if err := os.MkdirAll(p.dir, 0700); err != nil {
  27. return nil, err
  28. }
  29. ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)
  30. io := &IOPipe{}
  31. stdin, err := fifo.OpenFifo(ctx, p.fifo(syscall.Stdin), syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
  32. if err != nil {
  33. return nil, err
  34. }
  35. defer func() {
  36. if err != nil {
  37. stdin.Close()
  38. }
  39. }()
  40. io.Stdout, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stdout), syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
  41. if err != nil {
  42. return nil, err
  43. }
  44. defer func() {
  45. if err != nil {
  46. io.Stdout.Close()
  47. }
  48. }()
  49. if !terminal {
  50. io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(syscall.Stderr), syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700)
  51. if err != nil {
  52. return nil, err
  53. }
  54. defer func() {
  55. if err != nil {
  56. io.Stderr.Close()
  57. }
  58. }()
  59. } else {
  60. io.Stderr = ioutil.NopCloser(emptyReader{})
  61. }
  62. io.Stdin = ioutils.NewWriteCloserWrapper(stdin, func() error {
  63. stdin.Close()
  64. _, err := p.client.remote.apiClient.UpdateProcess(context.Background(), &containerd.UpdateProcessRequest{
  65. Id: p.containerID,
  66. Pid: p.friendlyName,
  67. CloseStdin: true,
  68. })
  69. return err
  70. })
  71. return io, nil
  72. }
  73. func (p *process) closeFifos(io *IOPipe) {
  74. io.Stdin.Close()
  75. io.Stdout.Close()
  76. io.Stderr.Close()
  77. }
  78. type emptyReader struct{}
  79. func (r emptyReader) Read(b []byte) (int, error) {
  80. return 0, io.EOF
  81. }
  82. func (p *process) fifo(index int) string {
  83. return filepath.Join(p.dir, p.friendlyName+"-"+fdNames[index])
  84. }