Move childPipe to the end of FD set
This adds a new env var for identifying the internal sync pipe that libcontainer uses to sync with the container and parent process. This replaces #496 to allow the user to add additional files to the processes and not take over fd 3 for all containers. Closes #496 Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
708b25e61e
commit
570eed473b
|
@ -16,6 +16,8 @@ import (
|
|||
"github.com/docker/libcontainer/configs"
|
||||
)
|
||||
|
||||
const stdioFdCount = 3
|
||||
|
||||
type linuxContainer struct {
|
||||
id string
|
||||
root string
|
||||
|
@ -139,7 +141,8 @@ func (c *linuxContainer) commandTemplate(p *Process, childPipe *os.File) (*exec.
|
|||
if cmd.SysProcAttr == nil {
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{}
|
||||
}
|
||||
cmd.ExtraFiles = append([]*os.File{childPipe}, p.ExtraFiles...)
|
||||
cmd.ExtraFiles = append(p.ExtraFiles, childPipe)
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("_LIBCONTAINER_INITPIPE=%d", stdioFdCount+len(cmd.ExtraFiles)-1))
|
||||
// NOTE: when running a container with no PID namespace and the parent process spawning the container is
|
||||
// PID1 the pdeathsig is being delivered to the container's init process by the kernel for some reason
|
||||
// even with the parent still running.
|
||||
|
@ -178,11 +181,9 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe,
|
|||
fmt.Sprintf("_LIBCONTAINER_INITPID=%d", c.initProcess.pid()),
|
||||
"_LIBCONTAINER_INITTYPE=setns",
|
||||
)
|
||||
|
||||
if p.consolePath != "" {
|
||||
cmd.Env = append(cmd.Env, "_LIBCONTAINER_CONSOLE_PATH="+p.consolePath)
|
||||
}
|
||||
|
||||
// TODO: set on container for process management
|
||||
return &setnsProcess{
|
||||
cmd: cmd,
|
||||
|
|
10
factory.go
10
factory.go
|
@ -33,14 +33,12 @@ type Factory interface {
|
|||
Load(id string) (Container, error)
|
||||
|
||||
// StartInitialization is an internal API to libcontainer used during the rexec of the
|
||||
// container. pipefd is the fd to the child end of the pipe used to syncronize the
|
||||
// parent and child process providing state and configuration to the child process and
|
||||
// returning any errors during the init of the container
|
||||
// container.
|
||||
//
|
||||
// Errors:
|
||||
// pipe connection error
|
||||
// system error
|
||||
StartInitialization(pipefd uintptr) error
|
||||
// Pipe connection error
|
||||
// System error
|
||||
StartInitialization() error
|
||||
|
||||
// Type returns info string about factory type (e.g. lxc, libcontainer...)
|
||||
Type() string
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/docker/pkg/mount"
|
||||
|
@ -194,7 +195,11 @@ func (l *LinuxFactory) Type() string {
|
|||
|
||||
// StartInitialization loads a container by opening the pipe fd from the parent to read the configuration and state
|
||||
// This is a low level implementation detail of the reexec and should not be consumed externally
|
||||
func (l *LinuxFactory) StartInitialization(pipefd uintptr) (err error) {
|
||||
func (l *LinuxFactory) StartInitialization() (err error) {
|
||||
pipefd, err := strconv.Atoi(os.Getenv("_LIBCONTAINER_INITPIPE"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var (
|
||||
pipe = os.NewFile(uintptr(pipefd), "pipe")
|
||||
it = initType(os.Getenv("_LIBCONTAINER_INITTYPE"))
|
||||
|
|
|
@ -96,21 +96,9 @@ func populateProcessEnvironment(env []string) error {
|
|||
// and working dir, and closes any leaked file descriptors
|
||||
// before executing the command inside the namespace
|
||||
func finalizeNamespace(config *initConfig) error {
|
||||
// FD 3 is the child pipe, which needs to be closed.
|
||||
// Additional file descriptors starts from 3 to (3 + n)
|
||||
// To fix the order all additional file descriptors
|
||||
// are shiftet by one right
|
||||
for fd := 3; fd < (config.PassedFilesCount + 3); fd++ {
|
||||
err := syscall.Dup2(fd+1, fd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that all unwanted fds we may have accidentally
|
||||
// inherited are marked close-on-exec so they stay out of the
|
||||
// container
|
||||
|
||||
if err := utils.CloseExecFrom(config.PassedFilesCount + 3); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func init() {
|
|||
if err != nil {
|
||||
log.Fatalf("unable to initialize for container: %s", err)
|
||||
}
|
||||
if err := factory.StartInitialization(3); err != nil {
|
||||
if err := factory.StartInitialization(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ var initCommand = cli.Command{
|
|||
if err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
if err := factory.StartInitialization(3); err != nil {
|
||||
if err := factory.StartInitialization(); err != nil {
|
||||
fatal(err)
|
||||
}
|
||||
panic("This line should never been executed")
|
||||
|
|
Loading…
Reference in New Issue