exec.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package exec // import "github.com/docker/docker/daemon/exec"
  2. import (
  3. "context"
  4. "runtime"
  5. "sync"
  6. "github.com/containerd/containerd/cio"
  7. "github.com/docker/docker/container/stream"
  8. "github.com/docker/docker/pkg/stringid"
  9. "github.com/sirupsen/logrus"
  10. )
  11. // Config holds the configurations for execs. The Daemon keeps
  12. // track of both running and finished execs so that they can be
  13. // examined both during and after completion.
  14. type Config struct {
  15. sync.Mutex
  16. Started chan struct{}
  17. StreamConfig *stream.Config
  18. ID string
  19. Running bool
  20. ExitCode *int
  21. OpenStdin bool
  22. OpenStderr bool
  23. OpenStdout bool
  24. CanRemove bool
  25. ContainerID string
  26. DetachKeys []byte
  27. Entrypoint string
  28. Args []string
  29. Tty bool
  30. Privileged bool
  31. User string
  32. WorkingDir string
  33. Env []string
  34. Pid int
  35. }
  36. // NewConfig initializes the a new exec configuration
  37. func NewConfig() *Config {
  38. return &Config{
  39. ID: stringid.GenerateRandomID(),
  40. StreamConfig: stream.NewConfig(),
  41. Started: make(chan struct{}),
  42. }
  43. }
  44. type rio struct {
  45. cio.IO
  46. sc *stream.Config
  47. }
  48. func (i *rio) Close() error {
  49. i.IO.Close()
  50. return i.sc.CloseStreams()
  51. }
  52. func (i *rio) Wait() {
  53. i.sc.Wait(context.Background())
  54. i.IO.Wait()
  55. }
  56. // InitializeStdio is called by libcontainerd to connect the stdio.
  57. func (c *Config) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) {
  58. c.StreamConfig.CopyToPipe(iop)
  59. if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" {
  60. if iop.Stdin != nil {
  61. if err := iop.Stdin.Close(); err != nil {
  62. logrus.Errorf("error closing exec stdin: %+v", err)
  63. }
  64. }
  65. }
  66. return &rio{IO: iop, sc: c.StreamConfig}, nil
  67. }
  68. // CloseStreams closes the stdio streams for the exec
  69. func (c *Config) CloseStreams() error {
  70. return c.StreamConfig.CloseStreams()
  71. }
  72. // SetExitCode sets the exec config's exit code
  73. func (c *Config) SetExitCode(code int) {
  74. c.ExitCode = &code
  75. }
  76. // Store keeps track of the exec configurations.
  77. type Store struct {
  78. byID map[string]*Config
  79. sync.RWMutex
  80. }
  81. // NewStore initializes a new exec store.
  82. func NewStore() *Store {
  83. return &Store{
  84. byID: make(map[string]*Config),
  85. }
  86. }
  87. // Commands returns the exec configurations in the store.
  88. func (e *Store) Commands() map[string]*Config {
  89. e.RLock()
  90. byID := make(map[string]*Config, len(e.byID))
  91. for id, config := range e.byID {
  92. byID[id] = config
  93. }
  94. e.RUnlock()
  95. return byID
  96. }
  97. // Add adds a new exec configuration to the store.
  98. func (e *Store) Add(id string, Config *Config) {
  99. e.Lock()
  100. e.byID[id] = Config
  101. e.Unlock()
  102. }
  103. // Get returns an exec configuration by its id.
  104. func (e *Store) Get(id string) *Config {
  105. e.RLock()
  106. res := e.byID[id]
  107. e.RUnlock()
  108. return res
  109. }
  110. // Delete removes an exec configuration from the store.
  111. func (e *Store) Delete(id string, pid int) {
  112. e.Lock()
  113. delete(e.byID, id)
  114. e.Unlock()
  115. }
  116. // List returns the list of exec ids in the store.
  117. func (e *Store) List() []string {
  118. var IDs []string
  119. e.RLock()
  120. for id := range e.byID {
  121. IDs = append(IDs, id)
  122. }
  123. e.RUnlock()
  124. return IDs
  125. }