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