2016-06-07 03:45:21 -04:00
|
|
|
// +build linux solaris
|
|
|
|
|
2016-03-18 14:50:19 -04:00
|
|
|
package libcontainerd
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
2016-10-14 19:31:27 -04:00
|
|
|
"io/ioutil"
|
2016-03-18 14:50:19 -04:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2016-06-07 03:45:21 -04:00
|
|
|
goruntime "runtime"
|
2016-10-14 19:31:27 -04:00
|
|
|
"time"
|
2016-03-18 14:50:19 -04:00
|
|
|
|
|
|
|
containerd "github.com/docker/containerd/api/grpc/types"
|
2016-10-14 19:31:27 -04:00
|
|
|
"github.com/tonistiigi/fifo"
|
2016-03-18 14:50:19 -04:00
|
|
|
"golang.org/x/net/context"
|
2016-06-07 03:45:21 -04:00
|
|
|
"golang.org/x/sys/unix"
|
2016-03-18 14:50:19 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
var fdNames = map[int]string{
|
2016-06-07 03:45:21 -04:00
|
|
|
unix.Stdin: "stdin",
|
|
|
|
unix.Stdout: "stdout",
|
|
|
|
unix.Stderr: "stderr",
|
2016-03-18 14:50:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// process keeps the state for both main container process and exec process.
|
|
|
|
type process struct {
|
|
|
|
processCommon
|
|
|
|
|
|
|
|
// Platform specific fields are below here.
|
|
|
|
dir string
|
|
|
|
}
|
|
|
|
|
2016-10-14 19:31:27 -04:00
|
|
|
func (p *process) openFifos(terminal bool) (pipe *IOPipe, err error) {
|
|
|
|
if err := os.MkdirAll(p.dir, 0700); err != nil {
|
2016-03-18 14:50:19 -04:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-10-14 19:31:27 -04:00
|
|
|
ctx, _ := context.WithTimeout(context.Background(), 15*time.Second)
|
2016-03-18 14:50:19 -04:00
|
|
|
|
|
|
|
io := &IOPipe{}
|
2016-10-14 19:31:27 -04:00
|
|
|
|
2016-06-07 03:45:21 -04:00
|
|
|
io.Stdin, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdin), unix.O_WRONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
2016-10-14 19:31:27 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
2016-10-18 14:18:19 -04:00
|
|
|
io.Stdin.Close()
|
2016-10-14 19:31:27 -04:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2016-06-07 03:45:21 -04:00
|
|
|
io.Stdout, err = fifo.OpenFifo(ctx, p.fifo(unix.Stdout), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
2016-03-18 14:50:19 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2016-10-14 19:31:27 -04:00
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
io.Stdout.Close()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
2016-06-07 03:45:21 -04:00
|
|
|
if goruntime.GOOS == "solaris" || !terminal {
|
|
|
|
// For Solaris terminal handling is done exclusively by the runtime therefore we make no distinction
|
|
|
|
// in the processing for terminal and !terminal cases.
|
|
|
|
io.Stderr, err = fifo.OpenFifo(ctx, p.fifo(unix.Stderr), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
2016-10-14 19:31:27 -04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer func() {
|
|
|
|
if err != nil {
|
|
|
|
io.Stderr.Close()
|
|
|
|
}
|
|
|
|
}()
|
2016-03-18 14:50:19 -04:00
|
|
|
} else {
|
2016-10-14 19:31:27 -04:00
|
|
|
io.Stderr = ioutil.NopCloser(emptyReader{})
|
2016-03-18 14:50:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return io, nil
|
|
|
|
}
|
|
|
|
|
2016-10-18 14:18:19 -04:00
|
|
|
func (p *process) sendCloseStdin() error {
|
|
|
|
_, err := p.client.remote.apiClient.UpdateProcess(context.Background(), &containerd.UpdateProcessRequest{
|
|
|
|
Id: p.containerID,
|
|
|
|
Pid: p.friendlyName,
|
|
|
|
CloseStdin: true,
|
|
|
|
})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2016-03-18 14:50:19 -04:00
|
|
|
func (p *process) closeFifos(io *IOPipe) {
|
|
|
|
io.Stdin.Close()
|
2016-10-14 19:31:27 -04:00
|
|
|
io.Stdout.Close()
|
|
|
|
io.Stderr.Close()
|
2016-03-18 14:50:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type emptyReader struct{}
|
|
|
|
|
|
|
|
func (r emptyReader) Read(b []byte) (int, error) {
|
|
|
|
return 0, io.EOF
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *process) fifo(index int) string {
|
|
|
|
return filepath.Join(p.dir, p.friendlyName+"-"+fdNames[index])
|
|
|
|
}
|