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