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  }