From 60f6b012eb9626a059b4d60c9492c20d09bc5271 Mon Sep 17 00:00:00 2001 From: Peter Volkov Date: Sun, 26 Jul 2026 11:32:39 +0300 Subject: [PATCH] cgroups: handle the cgroup v1 release_agent race The asynchronous release agent may remove an empty service cgroup after mkdir succeeds but before openrc-run writes the current process to its tasks file. The write then fails with ENOENT or ENODEV, leaving the service outside its per-service cgroup. Retry the complete create-and-attach operation. Once the tasks write succeeds, the populated cgroup can no longer be removed by the release agent. Fixes: https://github.com/OpenRC/openrc/issues/90 --- sh/rc-cgroup.sh | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sh/rc-cgroup.sh b/sh/rc-cgroup.sh index 547839655..a3c445d9a 100644 --- a/sh/rc-cgroup.sh +++ b/sh/rc-cgroup.sh @@ -104,7 +104,7 @@ cgroup_add_service() # it prevents unwanted inheriting of the user # cgroups. But may lead to problems where that inheriting # is needed. - local cgroup d openrc_cgroup + local attempts cgroup d openrc_cgroup for d in /sys/fs/cgroup/* ; do [ -w "${d}"/tasks ] && printf "%d" 0 > "${d}"/tasks done @@ -112,8 +112,18 @@ cgroup_add_service() openrc_cgroup=/sys/fs/cgroup/openrc if [ -d "$openrc_cgroup" ]; then cgroup="$openrc_cgroup/$RC_SVCNAME" - mkdir -p "$cgroup" - [ -w "$cgroup/tasks" ] && printf "%d" 0 > "$cgroup/tasks" + attempts=0 + # The asynchronous release agent may remove an empty cgroup + # between creating it and writing to tasks, so retry both. + while [ "$attempts" -lt 3 ]; do + mkdir -p "$cgroup" || return 0 + if [ -w "$cgroup/tasks" ] && + { printf "%d" 0 > "$cgroup/tasks"; } 2> /dev/null + then + return 0 + fi + attempts=$((attempts+1)) + done fi }