pkg/libcontainer/nsinit/sync_pipe.go
Alexander Larsson 0caa2d3992 libcontainer: Don't use UsetCloseOnExec, it is racy
We can't keep file descriptors without close-on-exec except with
syscall.ForkLock held, as otherwise they could leak by accident into
other children from forks in other threads.

Instead we just use Cmd.ExtraFiles which handles all this for us.

This fixes https://github.com/dotcloud/docker/issues/4493

Docker-DCO-1.1-Signed-off-by: Alexander Larsson <alexl@redhat.com> (github: alexlarsson)
2014-03-06 14:10:32 +01:00

71 lines
1.4 KiB
Go

package nsinit
import (
"encoding/json"
"fmt"
"github.com/dotcloud/docker/pkg/libcontainer"
"io/ioutil"
"os"
)
// SyncPipe allows communication to and from the child processes
// to it's parent and allows the two independent processes to
// syncronize their state.
type SyncPipe struct {
parent, child *os.File
}
func NewSyncPipe() (s *SyncPipe, err error) {
s = &SyncPipe{}
s.child, s.parent, err = os.Pipe()
if err != nil {
return nil, err
}
return s, nil
}
func NewSyncPipeFromFd(parendFd, childFd uintptr) (*SyncPipe, error) {
s := &SyncPipe{}
if parendFd > 0 {
s.parent = os.NewFile(parendFd, "parendPipe")
} else if childFd > 0 {
s.child = os.NewFile(childFd, "childPipe")
} else {
return nil, fmt.Errorf("no valid sync pipe fd specified")
}
return s, nil
}
func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
data, err := json.Marshal(context)
if err != nil {
return err
}
s.parent.Write(data)
return nil
}
func (s *SyncPipe) ReadFromParent() (libcontainer.Context, error) {
data, err := ioutil.ReadAll(s.child)
if err != nil {
return nil, fmt.Errorf("error reading from sync pipe %s", err)
}
var context libcontainer.Context
if len(data) > 0 {
if err := json.Unmarshal(data, &context); err != nil {
return nil, err
}
}
return context, nil
}
func (s *SyncPipe) Close() error {
if s.parent != nil {
s.parent.Close()
}
if s.child != nil {
s.child.Close()
}
return nil
}