132 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build !solaris
 | 
						|
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"os/exec"
 | 
						|
	"syscall"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/tonistiigi/fifo"
 | 
						|
	"golang.org/x/net/context"
 | 
						|
)
 | 
						|
 | 
						|
// setPDeathSig sets the parent death signal to SIGKILL so that if the
 | 
						|
// shim dies the container process also dies.
 | 
						|
func setPDeathSig() *syscall.SysProcAttr {
 | 
						|
	return &syscall.SysProcAttr{
 | 
						|
		Pdeathsig: syscall.SIGKILL,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// openIO opens the pre-created fifo's for use with the container
 | 
						|
// in RDWR so that they remain open if the other side stops listening
 | 
						|
func (p *process) openIO() error {
 | 
						|
	p.stdio = &stdio{}
 | 
						|
	var (
 | 
						|
		uid = p.state.RootUID
 | 
						|
		gid = p.state.RootGID
 | 
						|
	)
 | 
						|
 | 
						|
	ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)
 | 
						|
 | 
						|
	stdinCloser, err := fifo.OpenFifo(ctx, p.state.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	p.stdinCloser = stdinCloser
 | 
						|
 | 
						|
	if p.state.Terminal {
 | 
						|
		master, console, err := newConsole(uid, gid)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		p.console = master
 | 
						|
		p.consolePath = console
 | 
						|
		stdin, err := fifo.OpenFifo(ctx, p.state.Stdin, syscall.O_RDONLY, 0)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		go io.Copy(master, stdin)
 | 
						|
		stdoutw, err := fifo.OpenFifo(ctx, p.state.Stdout, syscall.O_WRONLY, 0)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		stdoutr, err := fifo.OpenFifo(ctx, p.state.Stdout, syscall.O_RDONLY, 0)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		p.Add(1)
 | 
						|
		go func() {
 | 
						|
			io.Copy(stdoutw, master)
 | 
						|
			master.Close()
 | 
						|
			stdoutr.Close()
 | 
						|
			stdoutw.Close()
 | 
						|
			p.Done()
 | 
						|
		}()
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	i, err := p.initializeIO(uid)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	p.shimIO = i
 | 
						|
	// non-tty
 | 
						|
	for name, dest := range map[string]func(wc io.WriteCloser, rc io.Closer){
 | 
						|
		p.state.Stdout: func(wc io.WriteCloser, rc io.Closer) {
 | 
						|
			p.Add(1)
 | 
						|
			go func() {
 | 
						|
				io.Copy(wc, i.Stdout)
 | 
						|
				p.Done()
 | 
						|
				wc.Close()
 | 
						|
				rc.Close()
 | 
						|
			}()
 | 
						|
		},
 | 
						|
		p.state.Stderr: func(wc io.WriteCloser, rc io.Closer) {
 | 
						|
			p.Add(1)
 | 
						|
			go func() {
 | 
						|
				io.Copy(wc, i.Stderr)
 | 
						|
				p.Done()
 | 
						|
				wc.Close()
 | 
						|
				rc.Close()
 | 
						|
			}()
 | 
						|
		},
 | 
						|
	} {
 | 
						|
		fw, err := fifo.OpenFifo(ctx, name, syscall.O_WRONLY, 0)
 | 
						|
		if err != nil {
 | 
						|
			return fmt.Errorf("containerd-shim: opening %s failed: %s", name, err)
 | 
						|
		}
 | 
						|
		fr, err := fifo.OpenFifo(ctx, name, syscall.O_RDONLY, 0)
 | 
						|
		if err != nil {
 | 
						|
			return fmt.Errorf("containerd-shim: opening %s failed: %s", name, err)
 | 
						|
		}
 | 
						|
		dest(fw, fr)
 | 
						|
	}
 | 
						|
 | 
						|
	f, err := fifo.OpenFifo(ctx, p.state.Stdin, syscall.O_RDONLY, 0)
 | 
						|
	if err != nil {
 | 
						|
		return fmt.Errorf("containerd-shim: opening %s failed: %s", p.state.Stdin, err)
 | 
						|
	}
 | 
						|
	go func() {
 | 
						|
		io.Copy(i.Stdin, f)
 | 
						|
		i.Stdin.Close()
 | 
						|
		f.Close()
 | 
						|
	}()
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (p *process) killAll() error {
 | 
						|
	if !p.state.Exec {
 | 
						|
		cmd := exec.Command(p.runtime, append(p.state.RuntimeArgs, "kill", "--all", p.id, "SIGKILL")...)
 | 
						|
		cmd.SysProcAttr = setPDeathSig()
 | 
						|
		out, err := cmd.CombinedOutput()
 | 
						|
		if err != nil {
 | 
						|
			return fmt.Errorf("%s: %v", out, err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 |