Skip to content

Containers without a cgroup: signal init on kill --all, warn if no pidns - #2431

Open
kolyshkin wants to merge 3 commits into
containers:mainfrom
kolyshkin:killall-no-cgroup
Open

kolyshkin wants to merge 3 commits into
containers:mainfrom
kolyshkin:killall-no-cgroup

Conversation

@kolyshkin

@kolyshkin kolyshkin commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

When a container has no cgroup (rootless with the cgroup creation error ignored, or --cgroup-manager=disabled), crun kill --all sends no signal at all and returns success. crun delete --force kills nothing when such a container also lacks its own PID namespace.

Podman uses kill --all to stop a container, so podman stop waits forever for a container which never got the signal.

Without a cgroup, the container processes cannot be found, so signal init instead. This is what runc does: when killing all processes via the cgroup fails for a rootless container, it warns and signals init. Do the same, warning when the container has no PID namespace of its own. For kill --all, a container which is not running is not an error, as with an empty cgroup.

Also, add a warning (as runc does) when a rootless container gets no cgroup and has no PID namespace of its own, since its processes cannot all be killed then. This makes the runc create [shared pidns + rootless] runc integration test pass, so it is removed from the skip list.

Related to: podman-container-tools/podman#30078

When a container has no cgroup (rootless with the cgroup creation error
ignored, or --cgroup-manager=disabled), "crun kill --all" sends no signal
at all and returns success, and "crun delete --force" kills nothing when
the container does not have its own PID namespace.

Podman uses "kill --all" to stop a container, so "podman stop" waits for
a container which never gets the signal.

Without a cgroup, the container processes cannot be found, so signal
init, which is what runc does in this case.  For "kill --all", do not
treat a container which is not running as an error, as with an empty
cgroup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@xz-dev

xz-dev commented Oct 31, 2026 •

Copy link
Copy Markdown

It would be great if we could ask Linux to support sending signals to a process tree, or broadcasting signals based on a "subreaper" process.

xz-dev added a commit to xz-dev/youki that referenced this pull request Oct 31, 2026
When the container init is not in the container cgroup, because the
rootless cgroup manager could not create it, kill_all_processes finds
no process and signals nothing.

Signal init too in this case, with a warning. With SIGKILL, that kills
all processes of a container which has its own PID namespace. runc
does the same when it can not kill the processes through the cgroup,
and containers/crun#2431 makes crun do it too.

Signed-off-by: Xiangzhe Zeng <xiangzhedev@gmail.com>
@kolyshkin

kolyshkin commented Oct 31, 2026 •

Copy link
Copy Markdown
Collaborator Author

It would be great if we could ask Linux to support sending signals to a process tree, or broadcasting signals based on a "subreaper" process.

There is such a thing already, actually, two!

  • cgroup + cgroup.kill;
  • pid namespace (you kill pid 1 and the whole pidns is gone).

I don't think we need a third mechanism :)

When the cgroup creation error is ignored for a rootless container,
and the container does not have its own PID namespace, its processes
cannot be found, and so cannot all be killed.

Warn about such configuration, as runc does.  Use libcrun_error, as
libcrun_warning is not shown with the default log level.

This makes the "runc create [shared pidns + rootless]" runc integration
test pass, so remove it from the skip list.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@kolyshkin kolyshkin changed the title container: signal init on kill --all without a cgroup Containers without a cgroup: signal init on kill --all, warn if no pidns Oct 31, 2026
container: signal init on kill --all without a cgroup

When a container has no cgroup (rootless with the cgroup creation error
ignored, or --cgroup-manager=disabled), "crun kill --all" sends no signal
at all and returns success, and "crun delete --force" kills nothing when
the container does not have its own PID namespace.

Podman uses "kill --all" to stop a container, so "podman stop" waits for
a container which never gets the signal.

Without a cgroup, the container processes cannot be found, so signal
init, which is what runc does in this case.  For "kill --all", do not
treat a container which is not running as an error, as with an empty
cgroup.

As runc, warn when signaling init only for a container without its own
PID namespace, as its other processes do not get the signal.  Use
libcrun_error, as libcrun_warning is not shown with the default log
level.

Assisted-by: Claude Code (claude-opus-5-5)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
@xz-dev

xz-dev commented Oct 31, 2026

Copy link
Copy Markdown

Thanks for the explanation, that makes sense. Just to check my understanding: both of those mechanisms seem to need some privileges for a rootless user, right?

  • cgroup.kill needs write access to a delegated cgroup (so cgroup delegation has to be set up, e.g. via systemd).

  • Killing pid 1 of a PID namespace needs the container to have its own pidns, which an unprivileged user can only create through a user namespace.

I was just curious how the no-cgroup / shared-pidns case is handled, and this PR answers that. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants