github.com/hinshun/containerd@v0.2.7/containerd-shim/process_linux.go (about)

     1  // +build !solaris
     2  
     3  package main
     4  
     5  import (
     6  	"fmt"
     7  	"io"
     8  	"os/exec"
     9  	"syscall"
    10  	"time"
    11  
    12  	"github.com/tonistiigi/fifo"
    13  	"golang.org/x/net/context"
    14  )
    15  
    16  // setPDeathSig sets the parent death signal to SIGKILL so that if the
    17  // shim dies the container process also dies.
    18  func setPDeathSig() *syscall.SysProcAttr {
    19  	return &syscall.SysProcAttr{
    20  		Pdeathsig: syscall.SIGKILL,
    21  	}
    22  }
    23  
    24  // openIO opens the pre-created fifo's for use with the container
    25  // in RDWR so that they remain open if the other side stops listening
    26  func (p *process) openIO() error {
    27  	p.stdio = &stdio{}
    28  	var (
    29  		uid = p.state.RootUID
    30  		gid = p.state.RootGID
    31  	)
    32  
    33  	ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)
    34  
    35  	stdinCloser, err := fifo.OpenFifo(ctx, p.state.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0)
    36  	if err != nil {
    37  		return err
    38  	}
    39  	p.stdinCloser = stdinCloser
    40  
    41  	if p.state.Terminal {
    42  		master, console, err := newConsole(uid, gid)
    43  		if err != nil {
    44  			return err
    45  		}
    46  		p.console = master
    47  		p.consolePath = console
    48  		stdin, err := fifo.OpenFifo(ctx, p.state.Stdin, syscall.O_RDONLY, 0)
    49  		if err != nil {
    50  			return err
    51  		}
    52  		go io.Copy(master, stdin)
    53  		stdoutw, err := fifo.OpenFifo(ctx, p.state.Stdout, syscall.O_WRONLY, 0)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		stdoutr, err := fifo.OpenFifo(ctx, p.state.Stdout, syscall.O_RDONLY, 0)
    58  		if err != nil {
    59  			return err
    60  		}
    61  		p.Add(1)
    62  		go func() {
    63  			io.Copy(stdoutw, master)
    64  			master.Close()
    65  			stdoutr.Close()
    66  			stdoutw.Close()
    67  			p.Done()
    68  		}()
    69  		return nil
    70  	}
    71  	i, err := p.initializeIO(uid)
    72  	if err != nil {
    73  		return err
    74  	}
    75  	p.shimIO = i
    76  	// non-tty
    77  	for name, dest := range map[string]func(wc io.WriteCloser, rc io.Closer){
    78  		p.state.Stdout: func(wc io.WriteCloser, rc io.Closer) {
    79  			p.Add(1)
    80  			go func() {
    81  				io.Copy(wc, i.Stdout)
    82  				p.Done()
    83  				wc.Close()
    84  				rc.Close()
    85  			}()
    86  		},
    87  		p.state.Stderr: func(wc io.WriteCloser, rc io.Closer) {
    88  			p.Add(1)
    89  			go func() {
    90  				io.Copy(wc, i.Stderr)
    91  				p.Done()
    92  				wc.Close()
    93  				rc.Close()
    94  			}()
    95  		},
    96  	} {
    97  		fw, err := fifo.OpenFifo(ctx, name, syscall.O_WRONLY, 0)
    98  		if err != nil {
    99  			return fmt.Errorf("containerd-shim: opening %s failed: %s", name, err)
   100  		}
   101  		fr, err := fifo.OpenFifo(ctx, name, syscall.O_RDONLY, 0)
   102  		if err != nil {
   103  			return fmt.Errorf("containerd-shim: opening %s failed: %s", name, err)
   104  		}
   105  		dest(fw, fr)
   106  	}
   107  
   108  	f, err := fifo.OpenFifo(ctx, p.state.Stdin, syscall.O_RDONLY, 0)
   109  	if err != nil {
   110  		return fmt.Errorf("containerd-shim: opening %s failed: %s", p.state.Stdin, err)
   111  	}
   112  	go func() {
   113  		io.Copy(i.Stdin, f)
   114  		i.Stdin.Close()
   115  		f.Close()
   116  	}()
   117  
   118  	return nil
   119  }
   120  
   121  func (p *process) killAll() error {
   122  	if !p.state.Exec {
   123  		cmd := exec.Command(p.runtime, append(p.state.RuntimeArgs, "kill", "--all", p.id, "SIGKILL")...)
   124  		cmd.SysProcAttr = setPDeathSig()
   125  		out, err := cmd.CombinedOutput()
   126  		if err != nil {
   127  			return fmt.Errorf("%s: %v", out, err)
   128  		}
   129  	}
   130  	return nil
   131  }