Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions distrobox-rm
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,60 @@ delete_container()

# Remove the container
printf "Removing container...\n"
# Workaround for podman rm --force timeout issue when cgroup-path is empty.
# See: https://github.com/chimera-linux/cports/issues/1718
#
# Background - cgroup delegation:
# In cgroup v2, only root can create sub-cgroups by default. "Delegation" means
# granting a non-root user write access to a cgroup subtree, allowing them to
# create child cgroups. On systemd systems, systemd-logind automatically delegates
# user slices (e.g., /sys/fs/cgroup/user.slice/user-1000.slice/) to users.
# On non-systemd systems (OpenRC/elogind), this delegation is NOT automatic -
# users lack write permission to /sys/fs/cgroup, so podman cannot create
# cgroups for containers. Similarly, if cgroup support is disabled entirely,
# even root cannot create cgroups.
#
# Root cause: Without available cgroup, crun cannot create a cgroup for the
# container. When cgroup-path is empty (or null), "crun kill --all" cannot
# enumerate processes via cgroup, causing podman rm --force to timeout waiting
# for the container to stop.
#
# Solution: Check if crun's cgroup-path is empty. If so, use "podman kill"
# first, which sends signal directly to the container's init process PID,
# bypassing the cgroup lookup issue.
#
# Why not try rm --force first then fallback to kill? Because that could mask
# other failures - we want to apply the workaround only when we know the
# specific condition (empty cgroup-path) that causes the timeout.
#
# Note: This only kills the init process. Processes started via "podman exec"
# (e.g., distrobox-enter) run in separate process groups and will become
# orphaned. Daemonized processes (setsid/double-fork) also cannot be tracked.
# Use --unshare-process when creating the container for full process cleanup.
# See: https://github.com/containers/podman/issues/11888
#
# To fix this properly, configure cgroup delegation:
# https://github.com/89luca89/distrobox/issues/1939
#
# distrobox-rm does not call distrobox-stop by design; a similar fix exists there.
if [ "${container_status}" = "running" ] && echo "${container_manager}" | grep -q "podman"; then
container_id=$(${container_manager} inspect --format '{{.Id}}' "${container_name}" 2> /dev/null)
if [ "${rootful}" -eq 0 ]; then
crun_status="/run/user/$(id -u)/crun/${container_id}/status"
else
crun_status="/run/crun/${container_id}/status"
fi
if [ -f "${crun_status}" ]; then
cgroup_path=$(sed -n 's/.*"cgroup-path": "\([^"]*\)".*/\1/p' "${crun_status}" 2> /dev/null)
if [ -z "${cgroup_path}" ]; then
${container_manager} kill "${container_name}" > /dev/null 2>&1 || :
printf >&2 "Warning: cgroup is not available for this container.\n"
printf >&2 "Warning: this is common on non-systemd systems (OpenRC/elogind) without cgroup delegation.\n"
printf >&2 "Warning: some child processes may remain running (orphaned).\n"
printf >&2 "Warning: to fix: https://github.com/89luca89/distrobox/issues/1939\n"
fi
fi
fi
# shellcheck disable=SC2086,SC2248
${container_manager} rm ${force_flag} --volumes "${container_name}"

Expand Down
54 changes: 53 additions & 1 deletion distrobox-stop
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,59 @@ case "${response}" in
y | Y | Yes | yes | YES)
# Stop the container
for container_name in ${container_name_list}; do
${container_manager} stop "${container_name}"
# Workaround for podman stop timeout issue when cgroup-path is empty.
# See: https://github.com/chimera-linux/cports/issues/1718
#
# Background - cgroup delegation:
# In cgroup v2, only root can create sub-cgroups by default. "Delegation" means
# granting a non-root user write access to a cgroup subtree, allowing them to
# create child cgroups. On systemd systems, systemd-logind automatically delegates
# user slices (e.g., /sys/fs/cgroup/user.slice/user-1000.slice/) to users.
# On non-systemd systems (OpenRC/elogind), this delegation is NOT automatic -
# users lack write permission to /sys/fs/cgroup, so podman cannot create
# cgroups for containers. Similarly, if cgroup support is disabled entirely,
# even root cannot create cgroups.
#
# Root cause: Without available cgroup, crun cannot create a cgroup for the
# container. When cgroup-path is empty (or null), "crun kill --all" cannot
# enumerate processes via cgroup, causing podman stop to timeout waiting for
# the container to stop.
#
# Solution: Check if crun's cgroup-path is empty. If so, use "podman kill"
# first, which sends signal directly to the container's init process PID,
# bypassing the cgroup lookup issue.
#
# Why not try stop first then fallback to kill? Because that could mask
# other failures - we want to apply the workaround only when we know the
# specific condition (empty cgroup-path) that causes the timeout.
#
# Note: This only kills the init process. Processes started via "podman exec"
# (e.g., distrobox-enter) run in separate process groups and will become
# orphaned. Daemonized processes (setsid/double-fork) also cannot be tracked.
# Use --unshare-process when creating the container for full process cleanup.
# See: https://github.com/containers/podman/issues/11888
#
# To fix this properly, configure cgroup delegation:
# https://github.com/89luca89/distrobox/issues/1939
if echo "${container_manager}" | grep -q "podman"; then
container_id=$(${container_manager} inspect --format '{{.Id}}' "${container_name}" 2> /dev/null)
if [ "${rootful}" -eq 0 ]; then
crun_status="/run/user/$(id -u)/crun/${container_id}/status"
else
crun_status="/run/crun/${container_id}/status"
fi
if [ -f "${crun_status}" ]; then
cgroup_path=$(sed -n 's/.*"cgroup-path": "\([^"]*\)".*/\1/p' "${crun_status}" 2> /dev/null)
if [ -z "${cgroup_path}" ]; then
${container_manager} kill "${container_name}" 2> /dev/null || :
printf >&2 "Warning: cgroup is not available for this container.\n"
printf >&2 "Warning: this is common on non-systemd systems (OpenRC/elogind) without cgroup delegation.\n"
printf >&2 "Warning: some child processes may remain running (orphaned).\n"
printf >&2 "Warning: to fix: https://github.com/89luca89/distrobox/issues/1939\n"
fi
fi
fi
${container_manager} stop "${container_name}" 2> /dev/null || :
done
;;
n | N | No | no | NO)
Expand Down