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