github.com/marunai/moby@v1.13.1/libcontainerd/process_unix.go (about)

     1  // +build linux solaris
     2  
     3  package libcontainerd
     4  
     5  import (
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	goruntime "runtime"
    11  	"strings"
    12  
    13  	containerd "github.com/docker/containerd/api/grpc/types"
    14  	"github.com/tonistiigi/fifo"
    15  	"golang.org/x/net/context"
    16  	"golang.org/x/sys/unix"
    17  )
    18  
    19  var fdNames = map[int]string{
    20  	unix.Stdin:  "stdin",
    21  	unix.Stdout: "stdout",
    22  	unix.Stderr: "stderr",
    23  }
    24  
    25  // process keeps the state for both main container process and exec process.
    26  type process struct {
    27  	processCommon
    28  
    29  	// Platform specific fields are below here.
    30  	dir string
    31  }
    32  
    33  func (p *process) openFifos(ctx context.Context, terminal bool) (pipe *IOPipe, err error) {
    34  	if err := os.MkdirAll(p.dir, 0700); err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	io := &IOPipe{}
    39  
    40  	io.Stdin, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdin), unix.O_WRONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	defer func() {
    46  		if err != nil {
    47  			io.Stdin.Close()
    48  		}
    49  	}()
    50  
    51  	io.Stdout, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdout), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  
    56  	defer func() {
    57  		if err != nil {
    58  			io.Stdout.Close()
    59  		}
    60  	}()
    61  
    62  	if goruntime.GOOS == "solaris" || !terminal {
    63  		// For Solaris terminal handling is done exclusively by the runtime therefore we make no distinction
    64  		// in the processing for terminal and !terminal cases.
    65  		io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(unix.Stderr), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
    66  		if err != nil {
    67  			return nil, err
    68  		}
    69  		defer func() {
    70  			if err != nil {
    71  				io.Stderr.Close()
    72  			}
    73  		}()
    74  	} else {
    75  		io.Stderr = ioutil.NopCloser(emptyReader{})
    76  	}
    77  
    78  	return io, nil
    79  }
    80  
    81  func (p *process) sendCloseStdin() error {
    82  	_, err := p.client.remote.apiClient.UpdateProcess(context.Background(), &containerd.UpdateProcessRequest{
    83  		Id:         p.containerID,
    84  		Pid:        p.friendlyName,
    85  		CloseStdin: true,
    86  	})
    87  	if err != nil && (strings.Contains(err.Error(), "container not found") || strings.Contains(err.Error(), "process not found")) {
    88  		return nil
    89  	}
    90  	return err
    91  }
    92  
    93  func (p *process) closeFifos(io *IOPipe) {
    94  	io.Stdin.Close()
    95  	io.Stdout.Close()
    96  	io.Stderr.Close()
    97  }
    98  
    99  type emptyReader struct{}
   100  
   101  func (r emptyReader) Read(b []byte) (int, error) {
   102  	return 0, io.EOF
   103  }
   104  
   105  func (p *process) fifo(index int) string {
   106  	return filepath.Join(p.dir, p.friendlyName+"-"+fdNames[index])
   107  }