github.com/mheon/docker@v0.11.2-0.20150922122814-44f47903a831/daemon/execdriver/native/exec.go (about)

     1  // +build linux
     2  
     3  package native
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/exec"
     9  	"syscall"
    10  
    11  	"github.com/docker/docker/daemon/execdriver"
    12  	"github.com/opencontainers/runc/libcontainer"
    13  	// Blank import 'nsenter' so that init in that package will call c
    14  	// function 'nsexec()' to do 'setns' before Go runtime take over,
    15  	// it's used for join to exist ns like 'docker exec' command.
    16  	_ "github.com/opencontainers/runc/libcontainer/nsenter"
    17  	"github.com/opencontainers/runc/libcontainer/utils"
    18  )
    19  
    20  // Exec implements the exec driver Driver interface,
    21  // it calls libcontainer APIs to execute a container.
    22  func (d *Driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, hooks execdriver.Hooks) (int, error) {
    23  	active := d.activeContainers[c.ID]
    24  	if active == nil {
    25  		return -1, fmt.Errorf("No active container exists with ID %s", c.ID)
    26  	}
    27  
    28  	p := &libcontainer.Process{
    29  		Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
    30  		Env:  c.ProcessConfig.Env,
    31  		Cwd:  c.WorkingDir,
    32  		User: processConfig.User,
    33  	}
    34  
    35  	if processConfig.Privileged {
    36  		p.Capabilities = execdriver.GetAllCapabilities()
    37  	}
    38  
    39  	config := active.Config()
    40  	if err := setupPipes(&config, processConfig, p, pipes); err != nil {
    41  		return -1, err
    42  	}
    43  
    44  	if err := active.Start(p); err != nil {
    45  		return -1, err
    46  	}
    47  
    48  	if hooks.Start != nil {
    49  		pid, err := p.Pid()
    50  		if err != nil {
    51  			p.Signal(os.Kill)
    52  			p.Wait()
    53  			return -1, err
    54  		}
    55  		hooks.Start(&c.ProcessConfig, pid)
    56  	}
    57  
    58  	ps, err := p.Wait()
    59  	if err != nil {
    60  		exitErr, ok := err.(*exec.ExitError)
    61  		if !ok {
    62  			return -1, err
    63  		}
    64  		ps = exitErr.ProcessState
    65  	}
    66  	return utils.ExitStatus(ps.Sys().(syscall.WaitStatus)), nil
    67  }