| package container // import "github.com/docker/docker/container" | |
| import ( | |
| "context" | |
| "runtime" | |
| "sync" | |
| "github.com/containerd/containerd/cio" | |
| "github.com/containerd/log" | |
| "github.com/docker/docker/container/stream" | |
| "github.com/docker/docker/libcontainerd/types" | |
| "github.com/docker/docker/pkg/stringid" | |
| ) | |
| // ExecConfig holds the configurations for execs. The Daemon keeps | |
| // track of both running and finished execs so that they can be | |
| // examined both during and after completion. | |
| type ExecConfig struct { | |
| sync.Mutex | |
| Started chan struct{} | |
| StreamConfig *stream.Config | |
| ID string | |
| Running bool | |
| ExitCode *int | |
| OpenStdin bool | |
| OpenStderr bool | |
| OpenStdout bool | |
| CanRemove bool | |
| Container *Container | |
| DetachKeys []byte | |
| Entrypoint string | |
| Args []string | |
| Tty bool | |
| Privileged bool | |
| User string | |
| WorkingDir string | |
| Env []string | |
| Process types.Process | |
| ConsoleSize *[2]uint | |
| } | |
| // NewExecConfig initializes the a new exec configuration | |
| func NewExecConfig(c *Container) *ExecConfig { | |
| return &ExecConfig{ | |
| ID: stringid.GenerateRandomID(), | |
| Container: c, | |
| StreamConfig: stream.NewConfig(), | |
| Started: make(chan struct{}), | |
| } | |
| } | |
| // InitializeStdio is called by libcontainerd to connect the stdio. | |
| func (c *ExecConfig) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) { | |
| c.StreamConfig.CopyToPipe(iop) | |
| if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" { | |
| if iop.Stdin != nil { | |
| if err := iop.Stdin.Close(); err != nil { | |
| log.G(context.TODO()).Errorf("error closing exec stdin: %+v", err) | |
| } | |
| } | |
| } | |
| return &rio{IO: iop, sc: c.StreamConfig}, nil | |
| } | |
| // CloseStreams closes the stdio streams for the exec | |
| func (c *ExecConfig) CloseStreams() error { | |
| return c.StreamConfig.CloseStreams() | |
| } | |
| // SetExitCode sets the exec config's exit code | |
| func (c *ExecConfig) SetExitCode(code int) { | |
| c.ExitCode = &code | |
| } | |
| // ExecStore keeps track of the exec configurations. | |
| type ExecStore struct { | |
| byID map[string]*ExecConfig | |
| mu sync.RWMutex | |
| } | |
| // NewExecStore initializes a new exec store. | |
| func NewExecStore() *ExecStore { | |
| return &ExecStore{ | |
| byID: make(map[string]*ExecConfig), | |
| } | |
| } | |
| // Commands returns the exec configurations in the store. | |
| func (e *ExecStore) Commands() map[string]*ExecConfig { | |
| e.mu.RLock() | |
| byID := make(map[string]*ExecConfig, len(e.byID)) | |
| for id, config := range e.byID { | |
| byID[id] = config | |
| } | |
| e.mu.RUnlock() | |
| return byID | |
| } | |
| // Add adds a new exec configuration to the store. | |
| func (e *ExecStore) Add(id string, Config *ExecConfig) { | |
| e.mu.Lock() | |
| e.byID[id] = Config | |
| e.mu.Unlock() | |
| } | |
| // Get returns an exec configuration by its id. | |
| func (e *ExecStore) Get(id string) *ExecConfig { | |
| e.mu.RLock() | |
| res := e.byID[id] | |
| e.mu.RUnlock() | |
| return res | |
| } | |
| // Delete removes an exec configuration from the store. | |
| func (e *ExecStore) Delete(id string) { | |
| e.mu.Lock() | |
| delete(e.byID, id) | |
| e.mu.Unlock() | |
| } | |
| // List returns the list of exec ids in the store. | |
| func (e *ExecStore) List() []string { | |
| var IDs []string | |
| e.mu.RLock() | |
| for id := range e.byID { | |
| IDs = append(IDs, id) | |
| } | |
| e.mu.RUnlock() | |
| return IDs | |
| } |