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