github.com/Heebron/moby@v0.0.0-20221111184709-6eab4f55faf7/container/exec.go (about)

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