From 791d53a21421fba249156ea3a503e9e04a4912e4 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Wed, 8 May 2019 13:49:07 +0200 Subject: rootless: use a pause process use a pause process to keep the user and mount namespace alive. The pause process is created immediately on reload, and all successive Podman processes will refer to it for joining the user&mount namespace. This solves all the race conditions we had on joining the correct namespaces using the conmon processes. As a fallback if the join fails for any reason (e.g. the pause process was killed), then we try to join the running containers as we were doing before. Signed-off-by: Giuseppe Scrivano --- cmd/podman/main_local.go | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'cmd/podman/main_local.go') diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index 7452965a2..2024d4b31 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -16,6 +16,7 @@ import ( "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/tracing" + "github.com/containers/libpod/pkg/util" "github.com/opentracing/opentracing-go" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -113,6 +114,34 @@ func setupRootless(cmd *cobra.Command, args []string) error { MainGlobalOpts, remoteclient, } + + pausePidPath, err := util.GetRootlessPauseProcessPidPath() + if err != nil { + return errors.Wrapf(err, "could not get pause process pid file path") + } + + data, err := ioutil.ReadFile(pausePidPath) + if err != nil && !os.IsNotExist(err) { + return errors.Wrapf(err, "cannot read pause process pid file %s", pausePidPath) + } + if err == nil { + pausePid, err := strconv.Atoi(string(data)) + if err != nil { + return errors.Wrapf(err, "cannot parse pause pid file %s", pausePidPath) + } + became, ret, err := rootless.JoinUserAndMountNS(uint(pausePid), "") + if err != nil { + logrus.Errorf("cannot join pause process pid %d. You may need to remove %s and stop all containers", pausePid, pausePidPath) + logrus.Errorf(err.Error()) + os.Exit(1) + } + if became { + os.Exit(ret) + } + } + + // if there is no pid file, try to join existing containers, and create a pause process. + runtime, err := libpodruntime.GetRuntime(getContext(), &podmanCmd) if err != nil { return errors.Wrapf(err, "could not get runtime") @@ -127,20 +156,20 @@ func setupRootless(cmd *cobra.Command, args []string) error { var became bool var ret int if len(ctrs) == 0 { - became, ret, err = rootless.BecomeRootInUserNS() + became, ret, err = rootless.BecomeRootInUserNS(pausePidPath) } else { for _, ctr := range ctrs { data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile) if err != nil { logrus.Errorf(err.Error()) - os.Exit(1) + continue } conmonPid, err := strconv.Atoi(string(data)) if err != nil { logrus.Errorf(err.Error()) - os.Exit(1) + continue } - became, ret, err = rootless.JoinUserAndMountNS(uint(conmonPid)) + became, ret, err = rootless.JoinUserAndMountNS(uint(conmonPid), pausePidPath) if err == nil { break } -- cgit v1.2.3-54-g00ecf From 9dabb16e6541a1b7bbb1c5a27a91e08863a5b491 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Thu, 9 May 2019 19:06:46 +0200 Subject: system: migrate stops the pause process Signed-off-by: Giuseppe Scrivano --- cmd/podman/main_local.go | 1 + libpod/runtime_migrate.go | 35 ++++++++++++++++++++++++++++++++++- libpod/runtime_migrate_unsupported.go | 11 +++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 libpod/runtime_migrate_unsupported.go (limited to 'cmd/podman/main_local.go') diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index 2024d4b31..5af05a11e 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -132,6 +132,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { became, ret, err := rootless.JoinUserAndMountNS(uint(pausePid), "") if err != nil { logrus.Errorf("cannot join pause process pid %d. You may need to remove %s and stop all containers", pausePid, pausePidPath) + logrus.Errorf("you can use `system migrate` to recreate the pause process") logrus.Errorf(err.Error()) os.Exit(1) } diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go index 116885d3a..e32e6edf6 100644 --- a/libpod/runtime_migrate.go +++ b/libpod/runtime_migrate.go @@ -1,14 +1,47 @@ +// +build linux + package libpod import ( "context" "fmt" + "io/ioutil" + "os" "path/filepath" + "strconv" + "syscall" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) +func stopPauseProcess() error { + if rootless.IsRootless() { + pausePidPath, err := util.GetRootlessPauseProcessPidPath() + if err != nil { + return errors.Wrapf(err, "could not get pause process pid file path") + } + data, err := ioutil.ReadFile(pausePidPath) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return errors.Wrapf(err, "cannot read pause process pid file %s", pausePidPath) + } + pausePid, err := strconv.Atoi(string(data)) + if err != nil { + return errors.Wrapf(err, "cannot parse pause pid file %s", pausePidPath) + } + if err := os.Remove(pausePidPath); err != nil { + return errors.Wrapf(err, "cannot delete pause pid file %s", pausePidPath) + } + syscall.Kill(pausePid, syscall.SIGKILL) + } + return nil +} + func (r *Runtime) migrate(ctx context.Context) error { runningContainers, err := r.GetRunningContainers() if err != nil { @@ -39,5 +72,5 @@ func (r *Runtime) migrate(ctx context.Context) error { } } - return nil + return stopPauseProcess() } diff --git a/libpod/runtime_migrate_unsupported.go b/libpod/runtime_migrate_unsupported.go new file mode 100644 index 000000000..1a9e46fdc --- /dev/null +++ b/libpod/runtime_migrate_unsupported.go @@ -0,0 +1,11 @@ +// +build !linux + +package libpod + +import ( + "context" +) + +func (r *Runtime) migrate(ctx context.Context) error { + return nil +} -- cgit v1.2.3-54-g00ecf