containerd/io_unix.go
Michael Crosby 06dc87ae59 Wait for client side copy goroutines to start
Make sure we wait for the client side copy goroutines to start coping
from the fifos before returning from the function.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
2017-08-17 10:58:56 -04:00

101 lines
1.9 KiB
Go

// +build !windows
package containerd
import (
"context"
"io"
"io/ioutil"
"os"
"path/filepath"
"sync"
"syscall"
"github.com/containerd/fifo"
)
// NewFifos returns a new set of fifos for the task
func NewFifos(id string) (*FIFOSet, error) {
root := filepath.Join(os.TempDir(), "containerd")
if err := os.MkdirAll(root, 0700); err != nil {
return nil, err
}
dir, err := ioutil.TempDir(root, "")
if err != nil {
return nil, err
}
return &FIFOSet{
Dir: dir,
In: filepath.Join(dir, id+"-stdin"),
Out: filepath.Join(dir, id+"-stdout"),
Err: filepath.Join(dir, id+"-stderr"),
}, nil
}
func copyIO(fifos *FIFOSet, ioset *ioSet, tty bool) (_ *wgCloser, err error) {
var (
f io.ReadWriteCloser
set []io.Closer
cwg sync.WaitGroup
ctx, cancel = context.WithCancel(context.Background())
wg = &sync.WaitGroup{}
)
defer func() {
if err != nil {
for _, f := range set {
f.Close()
}
cancel()
}
}()
if f, err = fifo.OpenFifo(ctx, fifos.In, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
return nil, err
}
set = append(set, f)
cwg.Add(1)
wg.Add(1)
go func(w io.WriteCloser) {
cwg.Done()
io.Copy(w, ioset.in)
w.Close()
wg.Done()
}(f)
if f, err = fifo.OpenFifo(ctx, fifos.Out, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
return nil, err
}
set = append(set, f)
wg.Add(1)
cwg.Add(1)
go func(r io.ReadCloser) {
cwg.Done()
io.Copy(ioset.out, r)
r.Close()
wg.Done()
}(f)
if f, err = fifo.OpenFifo(ctx, fifos.Err, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
return nil, err
}
set = append(set, f)
if !tty {
wg.Add(1)
cwg.Add(1)
go func(r io.ReadCloser) {
cwg.Done()
io.Copy(ioset.err, r)
r.Close()
wg.Done()
}(f)
}
cwg.Wait()
return &wgCloser{
wg: wg,
dir: fifos.Dir,
set: set,
cancel: cancel,
}, nil
}