exec.go 3.1 KB

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