daemon/exec/exec.go
9ca2e4e8
 package exec
 
 import (
37a3be24
 	"runtime"
9ca2e4e8
 	"sync"
 
aa3ce07c
 	"github.com/containerd/containerd/cio"
5ea75bb6
 	"github.com/docker/docker/container/stream"
9ca2e4e8
 	"github.com/docker/docker/pkg/stringid"
1009e6a4
 	"github.com/sirupsen/logrus"
9ca2e4e8
 )
 
 // Config 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 Config struct {
 	sync.Mutex
5ea75bb6
 	StreamConfig *stream.Config
 	ID           string
 	Running      bool
 	ExitCode     *int
 	OpenStdin    bool
 	OpenStderr   bool
 	OpenStdout   bool
 	CanRemove    bool
 	ContainerID  string
 	DetachKeys   []byte
 	Entrypoint   string
 	Args         []string
 	Tty          bool
 	Privileged   bool
 	User         string
19f2749d
 	WorkingDir   string
5ea75bb6
 	Env          []string
 	Pid          int
9ca2e4e8
 }
 
 // NewConfig initializes the a new exec configuration
 func NewConfig() *Config {
 	return &Config{
 		ID:           stringid.GenerateNonCryptoID(),
5ea75bb6
 		StreamConfig: stream.NewConfig(),
9ca2e4e8
 	}
 }
 
aa3ce07c
 type rio struct {
 	cio.IO
ddae20c0
 
 	sc *stream.Config
 }
 
aa3ce07c
 func (i *rio) Close() error {
ddae20c0
 	i.IO.Close()
 
 	return i.sc.CloseStreams()
 }
 
aa3ce07c
 func (i *rio) Wait() {
ddae20c0
 	i.sc.Wait()
 
 	i.IO.Wait()
 }
 
37a3be24
 // InitializeStdio is called by libcontainerd to connect the stdio.
3fec7c08
 func (c *Config) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) {
37a3be24
 	c.StreamConfig.CopyToPipe(iop)
 
5ea75bb6
 	if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" {
37a3be24
 		if iop.Stdin != nil {
 			if err := iop.Stdin.Close(); err != nil {
2f7e9078
 				logrus.Errorf("error closing exec stdin: %+v", err)
37a3be24
 			}
 		}
 	}
 
aa3ce07c
 	return &rio{IO: iop, sc: c.StreamConfig}, nil
37a3be24
 }
 
5ea75bb6
 // CloseStreams closes the stdio streams for the exec
 func (c *Config) CloseStreams() error {
 	return c.StreamConfig.CloseStreams()
 }
 
ebcb7d6b
 // SetExitCode sets the exec config's exit code
 func (c *Config) SetExitCode(code int) {
 	c.ExitCode = &code
 }
 
9ca2e4e8
 // Store keeps track of the exec configurations.
 type Store struct {
6f3e86e9
 	byID map[string]*Config
9ca2e4e8
 	sync.RWMutex
 }
 
 // NewStore initializes a new exec store.
 func NewStore() *Store {
ddae20c0
 	return &Store{
6f3e86e9
 		byID: make(map[string]*Config),
ddae20c0
 	}
9ca2e4e8
 }
 
 // Commands returns the exec configurations in the store.
 func (e *Store) Commands() map[string]*Config {
e5e62b96
 	e.RLock()
ddae20c0
 	byID := make(map[string]*Config, len(e.byID))
 	for id, config := range e.byID {
 		byID[id] = config
e5e62b96
 	}
 	e.RUnlock()
ddae20c0
 	return byID
9ca2e4e8
 }
 
 // Add adds a new exec configuration to the store.
 func (e *Store) Add(id string, Config *Config) {
 	e.Lock()
ddae20c0
 	e.byID[id] = Config
9ca2e4e8
 	e.Unlock()
 }
 
 // Get returns an exec configuration by its id.
 func (e *Store) Get(id string) *Config {
 	e.RLock()
ddae20c0
 	res := e.byID[id]
 	e.RUnlock()
 	return res
 }
 
9ca2e4e8
 // Delete removes an exec configuration from the store.
ddae20c0
 func (e *Store) Delete(id string, pid int) {
9ca2e4e8
 	e.Lock()
ddae20c0
 	delete(e.byID, id)
9ca2e4e8
 	e.Unlock()
 }
 
 // List returns the list of exec ids in the store.
 func (e *Store) List() []string {
 	var IDs []string
 	e.RLock()
ddae20c0
 	for id := range e.byID {
9ca2e4e8
 		IDs = append(IDs, id)
 	}
 	e.RUnlock()
 	return IDs
 }