summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go5
-rw-r--r--libpod/oci_conmon_linux.go24
-rw-r--r--libpod/options.go12
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 {