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