github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/daemon/exec/exec.go (about) 1 package exec 2 3 import ( 4 "fmt" 5 "sync" 6 "time" 7 8 "github.com/docker/docker/daemon/execdriver" 9 "github.com/docker/docker/pkg/stringid" 10 "github.com/docker/docker/runconfig" 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 *runconfig.StreamConfig 19 ID string 20 Running bool 21 ExitCode *int 22 ProcessConfig *execdriver.ProcessConfig 23 OpenStdin bool 24 OpenStderr bool 25 OpenStdout bool 26 CanRemove bool 27 ContainerID string 28 DetachKeys []byte 29 30 // waitStart will be closed immediately after the exec is really started. 31 waitStart chan struct{} 32 } 33 34 // NewConfig initializes the a new exec configuration 35 func NewConfig() *Config { 36 return &Config{ 37 ID: stringid.GenerateNonCryptoID(), 38 StreamConfig: runconfig.NewStreamConfig(), 39 waitStart: make(chan struct{}), 40 } 41 } 42 43 // Store keeps track of the exec configurations. 44 type Store struct { 45 commands map[string]*Config 46 sync.RWMutex 47 } 48 49 // NewStore initializes a new exec store. 50 func NewStore() *Store { 51 return &Store{commands: make(map[string]*Config, 0)} 52 } 53 54 // Commands returns the exec configurations in the store. 55 func (e *Store) Commands() map[string]*Config { 56 e.RLock() 57 commands := make(map[string]*Config, len(e.commands)) 58 for id, config := range e.commands { 59 commands[id] = config 60 } 61 e.RUnlock() 62 return commands 63 } 64 65 // Add adds a new exec configuration to the store. 66 func (e *Store) Add(id string, Config *Config) { 67 e.Lock() 68 e.commands[id] = Config 69 e.Unlock() 70 } 71 72 // Get returns an exec configuration by its id. 73 func (e *Store) Get(id string) *Config { 74 e.RLock() 75 res := e.commands[id] 76 e.RUnlock() 77 return res 78 } 79 80 // Delete removes an exec configuration from the store. 81 func (e *Store) Delete(id string) { 82 e.Lock() 83 delete(e.commands, id) 84 e.Unlock() 85 } 86 87 // List returns the list of exec ids in the store. 88 func (e *Store) List() []string { 89 var IDs []string 90 e.RLock() 91 for id := range e.commands { 92 IDs = append(IDs, id) 93 } 94 e.RUnlock() 95 return IDs 96 } 97 98 // Wait waits until the exec process finishes or there is an error in the error channel. 99 func (c *Config) Wait(cErr chan error) error { 100 // Exec should not return until the process is actually running 101 select { 102 case <-c.waitStart: 103 case err := <-cErr: 104 return err 105 } 106 return nil 107 } 108 109 // Close closes the wait channel for the progress. 110 func (c *Config) Close() { 111 close(c.waitStart) 112 } 113 114 // Resize changes the size of the terminal for the exec process. 115 func (c *Config) Resize(h, w int) error { 116 select { 117 case <-c.waitStart: 118 case <-time.After(time.Second): 119 return fmt.Errorf("Exec %s is not running, so it can not be resized.", c.ID) 120 } 121 return c.ProcessConfig.Terminal.Resize(h, w) 122 }