diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container.go | 5 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 24 | ||||
-rw-r--r-- | libpod/options.go | 12 |
3 files changed, 40 insertions, 1 deletions
diff --git a/libpod/container.go b/libpod/container.go index 20702903e..c85249676 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -418,6 +418,11 @@ type ContainerConfig struct { // HealthCheckConfig has the health check command and related timings HealthCheckConfig *manifest.Schema2HealthConfig `json:"healthcheck"` + + // PreserveFDs is a number of additional file descriptors (in addition + // to 0, 1, 2) that will be passed to the executed process. The total FDs + // passed will be 3 + PreserveFDs. + PreserveFDs uint `json:"preserveFds,omitempty"` } // ContainerNamedVolume is a named volume that will be mounted into the diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 625a5bf70..d8a89047e 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -904,6 +904,10 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co } } + if ctr.config.PreserveFDs > 0 { + args = append(args, formatRuntimeOpts("--preserve-fds", fmt.Sprintf("%d", ctr.config.PreserveFDs))...) + } + if restoreOptions != nil { args = append(args, "--restore", ctr.CheckpointPath()) if restoreOptions.TCPEstablished { @@ -935,8 +939,16 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co return err } + if ctr.config.PreserveFDs > 0 { + for fd := 3; fd < int(3+ctr.config.PreserveFDs); fd++ { + cmd.ExtraFiles = append(cmd.ExtraFiles, os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd))) + } + } + cmd.Env = r.conmonEnv - cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3), fmt.Sprintf("_OCI_STARTPIPE=%d", 4)) + // we don't want to step on users fds they asked to preserve + // Since 0-2 are used for stdio, start the fds we pass in at preserveFDs+3 + cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_SYNCPIPE=%d", ctr.config.PreserveFDs+3), fmt.Sprintf("_OCI_STARTPIPE=%d", ctr.config.PreserveFDs+4)) cmd.Env = append(cmd.Env, conmonEnv...) cmd.ExtraFiles = append(cmd.ExtraFiles, childSyncPipe, childStartPipe) cmd.ExtraFiles = append(cmd.ExtraFiles, envFiles...) @@ -1018,6 +1030,16 @@ func (r *ConmonOCIRuntime) createOCIContainer(ctr *Container, restoreOptions *Co ctr.state.ConmonPID = conmonPID } + if ctr.config.PreserveFDs > 0 { + for fd := 3; fd < int(3+ctr.config.PreserveFDs); fd++ { + // These fds were passed down to the runtime. Close them + // and not interfere + if err := os.NewFile(uintptr(fd), fmt.Sprintf("fd-%d", fd)).Close(); err != nil { + logrus.Debugf("unable to close file fd-%d", fd) + } + } + } + return nil } diff --git a/libpod/options.go b/libpod/options.go index ffc9c1018..7a60870a0 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1369,6 +1369,18 @@ func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption } } +// WithPreserveFDs forwards from the process running Libpod into the container +// the given number of extra FDs (starting after the standard streams) to the created container +func WithPreserveFDs(fd uint) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return define.ErrCtrFinalized + } + ctr.config.PreserveFDs = fd + return nil + } +} + // WithCreateCommand adds the full command plus arguments of the current // process to the container config. func WithCreateCommand() CtrCreateOption { |