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