exec.go 2.9 KB

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