github.com/moby/docker@v26.1.3+incompatible/container/exec.go (about)

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