mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-10 21:53:57 +08:00
runc exec: reject paused container unless --ignore-paused
Currently, if a container is paused (i.e. its cgroup is frozen), runc exec just hangs, and it is not obvious why. Refuse to exec in a paused container. Add a test case. In case runc exec in a paused container is a legit use case, add --ignore-paused option to override the check. Document it, add a test case. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
@@ -173,6 +173,7 @@ _runc_exec() {
|
|||||||
--apparmor
|
--apparmor
|
||||||
--cap, -c
|
--cap, -c
|
||||||
--preserve-fds
|
--preserve-fds
|
||||||
|
--ignore-paused
|
||||||
"
|
"
|
||||||
|
|
||||||
local all_options="$options_with_args $boolean_options"
|
local all_options="$options_with_args $boolean_options"
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ following will output a list of processes running in the container:
|
|||||||
Name: "cgroup",
|
Name: "cgroup",
|
||||||
Usage: "run the process in an (existing) sub-cgroup(s). Format is [<controller>:]<cgroup>.",
|
Usage: "run the process in an (existing) sub-cgroup(s). Format is [<controller>:]<cgroup>.",
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "ignore-paused",
|
||||||
|
Usage: "allow exec in a paused container",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Action: func(context *cli.Context) error {
|
Action: func(context *cli.Context) error {
|
||||||
if err := checkArgs(context, 1, minArgs); err != nil {
|
if err := checkArgs(context, 1, minArgs); err != nil {
|
||||||
@@ -145,7 +149,10 @@ func execProcess(context *cli.Context) (int, error) {
|
|||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
if status == libcontainer.Stopped {
|
if status == libcontainer.Stopped {
|
||||||
return -1, errors.New("cannot exec a container that has stopped")
|
return -1, errors.New("cannot exec in a stopped container")
|
||||||
|
}
|
||||||
|
if status == libcontainer.Paused && !context.Bool("ignore-paused") {
|
||||||
|
return -1, errors.New("cannot exec in a paused container (use --ignore-paused to override)")
|
||||||
}
|
}
|
||||||
path := context.String("process")
|
path := context.String("process")
|
||||||
if path == "" && len(context.Args()) == 1 {
|
if path == "" && len(context.Args()) == 1 {
|
||||||
|
|||||||
@@ -59,6 +59,11 @@ multiple times.
|
|||||||
: Pass _N_ additional file descriptors to the container (**stdio** +
|
: Pass _N_ additional file descriptors to the container (**stdio** +
|
||||||
**$LISTEN_FDS** + _N_ in total). Default is **0**.
|
**$LISTEN_FDS** + _N_ in total). Default is **0**.
|
||||||
|
|
||||||
|
**--ignore-paused**
|
||||||
|
: Allow exec in a paused container. By default, if a container is paused,
|
||||||
|
**runc exec** errors out; this option can be used to override it.
|
||||||
|
A paused container needs to be resumed for the exec to complete.
|
||||||
|
|
||||||
**--cgroup** _path_ | _controller_[,_controller_...]:_path_
|
**--cgroup** _path_ | _controller_[,_controller_...]:_path_
|
||||||
: Execute a process in a sub-cgroup. If the specified cgroup does not exist, an
|
: Execute a process in a sub-cgroup. If the specified cgroup does not exist, an
|
||||||
error is returned. Default is empty path, which means to use container's top
|
error is returned. Default is empty path, which means to use container's top
|
||||||
|
|||||||
@@ -303,3 +303,47 @@ function setup() {
|
|||||||
# check that the cgroups v2 path is the same for both processes
|
# check that the cgroups v2 path is the same for both processes
|
||||||
[[ "$run_cgroup" == "$exec_cgroup" ]]
|
[[ "$run_cgroup" == "$exec_cgroup" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "runc exec should refuse a paused container" {
|
||||||
|
if [[ "$ROOTLESS" -ne 0 ]]; then
|
||||||
|
requires rootless_cgroup
|
||||||
|
fi
|
||||||
|
requires cgroups_freezer
|
||||||
|
|
||||||
|
set_cgroups_path
|
||||||
|
|
||||||
|
runc run -d --console-socket "$CONSOLE_SOCKET" ct1
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
runc pause ct1
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
|
# Exec should not timeout or succeed.
|
||||||
|
runc exec ct1 echo ok
|
||||||
|
[ "$status" -eq 255 ]
|
||||||
|
[[ "$output" == *"cannot exec in a paused container"* ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "runc exec --ignore-paused" {
|
||||||
|
if [[ "$ROOTLESS" -ne 0 ]]; then
|
||||||
|
requires rootless_cgroup
|
||||||
|
fi
|
||||||
|
requires cgroups_freezer
|
||||||
|
|
||||||
|
set_cgroups_path
|
||||||
|
|
||||||
|
runc run -d --console-socket "$CONSOLE_SOCKET" ct1
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
runc pause ct1
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
|
# Resume the container a bit later.
|
||||||
|
(
|
||||||
|
sleep 2
|
||||||
|
runc resume ct1
|
||||||
|
) &
|
||||||
|
|
||||||
|
# Exec should not timeout or succeed.
|
||||||
|
runc exec --ignore-paused ct1 echo ok
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ "$output" = "ok" ]
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user