aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libpod/container_api.go24
-rw-r--r--libpod/oci.go4
-rw-r--r--libpod/util.go44
-rw-r--r--pkg/util/utils.go32
-rw-r--r--test/e2e/rootless_test.go4
-rw-r--r--vendor.conf2
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go6
7 files changed, 97 insertions, 19 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go
index df6b6e962..e1d5e15c4 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -328,6 +328,11 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
if err != nil {
return errors.Wrapf(err, "error exec %s", c.ID())
}
+ chWait := make(chan error)
+ go func() {
+ chWait <- execCmd.Wait()
+ }()
+ defer close(chWait)
pidFile := c.execPidPath(sessionID)
// 60 second seems a reasonable time to wait
@@ -336,18 +341,12 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
const pidWaitTimeout = 60000
// Wait until the runtime makes the pidfile
- // TODO: If runtime errors before the PID file is created, we have to
- // wait for timeout here
- if err := WaitForFile(pidFile, pidWaitTimeout*time.Millisecond); err != nil {
- logrus.Debugf("Timed out waiting for pidfile from runtime for container %s exec", c.ID())
-
- // Check if an error occurred in the process before we made a pidfile
- // TODO: Wait() here is a poor choice - is there a way to see if
- // a process has finished, instead of waiting for it to finish?
- if err := execCmd.Wait(); err != nil {
+ exited, err := WaitForFile(pidFile, chWait, pidWaitTimeout*time.Millisecond)
+ if err != nil {
+ if exited {
+ // If the runtime exited, propagate the error we got from the process.
return err
}
-
return errors.Wrapf(err, "timed out waiting for runtime to create pidfile for exec session in container %s", c.ID())
}
@@ -389,7 +388,10 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user string) e
locked = false
}
- waitErr := execCmd.Wait()
+ var waitErr error
+ if !exited {
+ waitErr = <-chWait
+ }
// Lock again
if !c.batched {
diff --git a/libpod/oci.go b/libpod/oci.go
index e9cceda82..4460402ed 100644
--- a/libpod/oci.go
+++ b/libpod/oci.go
@@ -316,6 +316,10 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string, res
cmd.Env = append(r.conmonEnv, fmt.Sprintf("_OCI_SYNCPIPE=%d", 3))
cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_STARTPIPE=%d", 4))
cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("_LIBPOD_USERNS_CONFIGURED=%s", os.Getenv("_LIBPOD_USERNS_CONFIGURED")))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("_LIBPOD_ROOTLESS_UID=%s", os.Getenv("_LIBPOD_ROOTLESS_UID")))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("HOME=%s", os.Getenv("HOME")))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
if r.reservePorts {
ports, err := bindPorts(ctr.config.PortMappings)
diff --git a/libpod/util.go b/libpod/util.go
index 7007b29cd..aa3494529 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -13,6 +13,7 @@ import (
"github.com/containers/image/signature"
"github.com/containers/image/types"
"github.com/containers/libpod/pkg/util"
+ "github.com/fsnotify/fsnotify"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
@@ -90,31 +91,64 @@ func MountExists(specMounts []spec.Mount, dest string) bool {
}
// WaitForFile waits until a file has been created or the given timeout has occurred
-func WaitForFile(path string, timeout time.Duration) error {
+func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, error) {
done := make(chan struct{})
chControl := make(chan struct{})
+
+ var inotifyEvents chan fsnotify.Event
+ var timer chan struct{}
+ watcher, err := fsnotify.NewWatcher()
+ if err == nil {
+ if err := watcher.Add(filepath.Dir(path)); err == nil {
+ inotifyEvents = watcher.Events
+ }
+ defer watcher.Close()
+ }
+ if inotifyEvents == nil {
+ // If for any reason we fail to create the inotify
+ // watcher, fallback to polling the file
+ timer = make(chan struct{})
+ go func() {
+ select {
+ case <-chControl:
+ close(timer)
+ return
+ default:
+ time.Sleep(25 * time.Millisecond)
+ timer <- struct{}{}
+ }
+ }()
+ }
+
go func() {
for {
select {
case <-chControl:
return
- default:
+ case <-timer:
+ _, err := os.Stat(path)
+ if err == nil {
+ close(done)
+ return
+ }
+ case <-inotifyEvents:
_, err := os.Stat(path)
if err == nil {
close(done)
return
}
- time.Sleep(25 * time.Millisecond)
}
}
}()
select {
+ case e := <-chWait:
+ return true, e
case <-done:
- return nil
+ return false, nil
case <-time.After(timeout):
close(chControl)
- return errors.Wrapf(ErrInternal, "timed out waiting for file %s", path)
+ return false, errors.Wrapf(ErrInternal, "timed out waiting for file %s", path)
}
}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index c5ba38b9f..de29bc5d8 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -284,6 +284,35 @@ func GetRootlessStorageOpts() (storage.StoreOptions, error) {
return opts, nil
}
+type tomlOptionsConfig struct {
+ MountProgram string `toml:"mount_program"`
+}
+
+type tomlConfig struct {
+ Storage struct {
+ Driver string `toml:"driver"`
+ RunRoot string `toml:"runroot"`
+ GraphRoot string `toml:"graphroot"`
+ Options struct{ tomlOptionsConfig } `toml:"options"`
+ } `toml:"storage"`
+}
+
+func getTomlStorage(storeOptions *storage.StoreOptions) *tomlConfig {
+ config := new(tomlConfig)
+
+ config.Storage.Driver = storeOptions.GraphDriverName
+ config.Storage.RunRoot = storeOptions.RunRoot
+ config.Storage.GraphRoot = storeOptions.GraphRoot
+ for _, i := range storeOptions.GraphDriverOptions {
+ s := strings.Split(i, "=")
+ if s[0] == "overlay.mount_program" {
+ config.Storage.Options.MountProgram = s[1]
+ }
+ }
+
+ return config
+}
+
// GetDefaultStoreOptions returns the storage ops for containers
func GetDefaultStoreOptions() (storage.StoreOptions, error) {
storageOpts := storage.DefaultStoreOptions
@@ -304,9 +333,10 @@ func GetDefaultStoreOptions() (storage.StoreOptions, error) {
return storageOpts, errors.Wrapf(err, "cannot open %s", storageConf)
}
+ tomlConfiguration := getTomlStorage(&storageOpts)
defer file.Close()
enc := toml.NewEncoder(file)
- if err := enc.Encode(storageOpts); err != nil {
+ if err := enc.Encode(tomlConfiguration); err != nil {
os.Remove(storageConf)
}
}
diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go
index 9f84d4c13..c75910296 100644
--- a/test/e2e/rootless_test.go
+++ b/test/e2e/rootless_test.go
@@ -205,6 +205,10 @@ var _ = Describe("Podman rootless", func() {
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
+ cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l", "--type", "container", "--format", "{{ .State.Status }}"}, 1000, 1000, env)
+ cmd.WaitWithDefaultTimeout()
+ Expect(cmd.LineInOutputContains("exited")).To(BeTrue())
+
cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, env)
cmd.WaitWithDefaultTimeout()
Expect(cmd.ExitCode()).To(Equal(0))
diff --git a/vendor.conf b/vendor.conf
index 0c05e792c..f9fccfdfb 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -51,7 +51,7 @@ github.com/opencontainers/image-spec v1.0.0
github.com/opencontainers/runc b4e2ecb452d9ee4381137cc0a7e6715b96bed6de
github.com/opencontainers/runtime-spec d810dbc60d8c5aeeb3d054bd1132fab2121968ce
github.com/opencontainers/runtime-tools master
-github.com/opencontainers/selinux 36a9bc45a08c85f2c52bd9eb32e20267876773bd
+github.com/opencontainers/selinux 6ba084dd09db3dfe49a839bab0bbe97fd9274d80
github.com/ostreedev/ostree-go master
github.com/pkg/errors v0.8.0
github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
index 2cd54eac1..bbaa1e0d7 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
@@ -687,7 +687,11 @@ func Chcon(fpath string, label string, recurse bool) error {
return err
}
callback := func(p string, info os.FileInfo, err error) error {
- return SetFileLabel(p, label)
+ e := SetFileLabel(p, label)
+ if os.IsNotExist(e) {
+ return nil
+ }
+ return e
}
if recurse {