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) Upstream-commit: 5c9b28db1853cccdf7a1037eeaad372d12cd68fa Component: engine
72 lines
1.4 KiB
Go
72 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
|
|
}
|