openrc/sh/rc-cgroup.sh.in

206 lines
5.4 KiB
Bash

#!@SHELL@
# Copyright (c) 2012-2015 The OpenRC Authors.
# See the Authors file at the top-level directory of this distribution and
# https://github.com/OpenRC/openrc/blob/master/AUTHORS
#
# This file is part of OpenRC. It is subject to the license terms in
# the LICENSE file found in the top-level directory of this
# distribution and at https://github.com/OpenRC/openrc/blob/master/LICENSE
# This file may not be copied, modified, propagated, or distributed
# except according to the terms contained in the LICENSE file.
extra_stopped_commands="${extra_stopped_commands} cgroup_cleanup"
description_cgroup_cleanup="Kill all processes in the cgroup"
cgroup_find_path()
{
local OIFS n name dir result
[ -n "$1" ] || return 0
OIFS="$IFS"
IFS=":"
while read n name dir; do
[ "$name" = "$1" ] && result="$dir"
done < /proc/1/cgroup
IFS="$OIFS"
echo $result
}
cgroup_get_pids()
{
local p
pids=
while read p; do
[ $p -eq $$ ] || pids="${pids} ${p}"
done < /sys/fs/cgroup/openrc/${RC_SVCNAME}/tasks
[ -n "$pids" ]
}
cgroup_running()
{
[ -d "/sys/fs/cgroup/openrc/${RC_SVCNAME}" ]
}
cgroup_set_values()
{
[ -n "$1" -a -n "$2" -a -d "/sys/fs/cgroup/$1" ] || return 0
local controller="$1" h=$(cgroup_find_path "$1")
cgroup="/sys/fs/cgroup/${1}${h}openrc_${RC_SVCNAME}"
[ -d "$cgroup" ] || mkdir -p "$cgroup"
set -- $2
local name val
while [ -n "$1" -a "$controller" != "cpuacct" ]; do
case "$1" in
$controller.*)
if [ -n "$name" -a -w "$cgroup/$name" -a -n "$val" ]; then
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
printf "%s" "$val" > "$cgroup/$name"
fi
name=$1
val=
;;
*)
[ -n "$val" ] &&
val="$val $1" ||
val="$1"
;;
esac
shift
done
if [ -n "$name" -a -w "$cgroup/$name" -a -n "$val" ]; then
veinfo "$RC_SVCNAME: Setting $cgroup/$name to $val"
printf "%s" "$val" > "$cgroup/$name"
fi
if [ -w "$cgroup/tasks" ]; then
veinfo "$RC_SVCNAME: adding to $cgroup/tasks"
printf "%d" 0 > "$cgroup/tasks"
fi
return 0
}
cgroup_add_service()
{
# relocate starting process to the top of the cgroup
# it prevents from unwanted inheriting of the user
# cgroups. But may lead to a problems where that inheriting
# is needed.
for d in /sys/fs/cgroup/* ; do
[ -w "${d}"/tasks ] && printf "%d" 0 > "${d}"/tasks
done
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"
fi
}
cgroup_set_limits()
{
local blkio="${rc_cgroup_blkio:-$RC_CGROUP_BLKIO}"
[ -n "$blkio" ] && cgroup_set_values blkio "$blkio"
local cpu="${rc_cgroup_cpu:-$RC_CGROUP_CPU}"
[ -n "$cpu" ] && cgroup_set_values cpu "$cpu"
local cpuacct="${rc_cgroup_cpuacct:-$RC_CGROUP_CPUACCT}"
[ -n "$cpuacct" ] && cgroup_set_values cpuacct "$cpuacct"
local cpuset="${rc_cgroup_cpuset:-$RC_CGROUP_cpuset}"
[ -n "$cpuset" ] && cgroup_set_values cpuset "$cpuset"
local devices="${rc_cgroup_devices:-$RC_CGROUP_DEVICES}"
[ -n "$devices" ] && cgroup_set_values devices "$devices"
local hugetlb="${rc_cgroup_hugetlb:-$RC_CGROUP_HUGETLB}"
[ -n "$hugetlb" ] && cgroup_set_values hugetlb "$hugetlb"
local memory="${rc_cgroup_memory:-$RC_CGROUP_MEMORY}"
[ -n "$memory" ] && cgroup_set_values memory "$memory"
local net_cls="${rc_cgroup_net_cls:-$RC_CGROUP_NET_CLS}"
[ -n "$net_cls" ] && cgroup_set_values net_cls "$net_cls"
local net_prio="${rc_cgroup_net_prio:-$RC_CGROUP_NET_PRIO}"
[ -n "$net_prio" ] && cgroup_set_values net_prio "$net_prio"
local pids="${rc_cgroup_pids:-$RC_CGROUP_PIDS}"
[ -n "$pids" ] && cgroup_set_values pids "$pids"
return 0
}
cgroup2_find_path()
{
case "${rc_cgroup_mode:-hybrid}" in
hybrid) printf "/sys/fs/cgroup/unified" ;;
unified) printf "/sys/fs/cgroup" ;;
esac
return 0
}
cgroup2_remove()
{
local cgroup_path="$(cgroup2_find_path)" rc_cgroup_path
[ -z "${cgroup_path}" ] && return 0
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
[ ! -d "${rc_cgroup_path}" ] ||
[ ! -e "${rc_cgroup_path}"/cgroup.events ] &&
return 0
grep -qx "$$" "${rc_cgroup_path}/cgroup.procs" &&
echo 0 > "${cgroup_path}/cgroup.procs"
local key populated vvalue
while read key value; do
case "${key}" in
populated) populated=${value} ;;
*) ;;
esac
done < "${rc_cgroup_path}/cgroup.events"
[ "${populated}" = 1 ] && return 0
rmdir "${rc_cgroup_path}"
return 0
}
cgroup2_set_limits()
{
local cgroup_path="$(cgroup2_find_path)"
[ -z "${cgroup_path}" ] && return 0
rc_cgroup_path="${cgroup_path}/${RC_SVCNAME}"
local OIFS="$IFS"
IFS="
"
[ ! -d "${rc_cgroup_path}" ] && mkdir "${rc_cgroup_path}"
echo 0 > "${rc_cgroup_path}/cgroup.procs"
echo "${rc_cgroup_settings}" | while IFS="$OIFS" read key value; do
[ -z "${key}" ] || [ -z "${value}" ] && continue
[ ! -e "${rc_cgroup_path}/${key}" ] && continue
veinfo "${RC_SVCNAME}: cgroups: ${key} ${value}"
echo "${value}" > "${rc_cgroup_path}/${key}"
done
IFS="$OIFS"
return 0
}
cgroup_cleanup()
{
cgroup_running || return 0
ebegin "starting cgroups cleanup"
for sig in TERM QUIT INT; do
cgroup_get_pids || { eend 0 "finished" ; return 0 ; }
for i in 0 1; do
kill -s $sig $pids
for j in 0 1 2; do
cgroup_get_pids || { eend 0 "finished" ; return 0 ; }
sleep 1
done
done 2>/dev/null
done
cgroup_get_pids || { eend 0 "finished" ; return 0; }
kill -9 $pids
eend $(cgroup_running && echo 1 || echo 0) "fail to stop all processes"
}