Bug report
cgroup_reader in ros2_medkit_linux_introspection reports container limits
only for one of the three common cgroup layouts. In the other two it either
fails completely or silently returns nothing.
Both problems are in
src/ros2_medkit_discovery_plugins/ros2_medkit_linux_introspection/src/linux_utils/cgroup_reader.cpp.
1. cgroup v1 is not handled.
read_cgroup_path() only matches the cgroup v2 line format:
if (line.rfind("0::", 0) == 0) {
return line.substr(3);
}
On a pure cgroup v1 host every line has the form <id>:<controllers>:<path>, so
no line matches, the function returns an empty string, and read_cgroup_info()
gives up.
2. The filesystem path is built for cgroupns=host only.
auto cgroup_fs_path = root + "/sys/fs/cgroup" + cgroup_path;
This assumes /proc/self/cgroup reports a path like /docker/<id>, which is the
case with cgroupns=host. With cgroupns=private, which is the default in
current Docker, the container sees its own cgroup mounted directly at
/sys/fs/cgroup and the reported path is usually /. The concatenation then
gives /sys/fs/cgroup//cpu.max, which happens to resolve. Any private namespace
with a path other than / builds a path that does not exist, and the limits are
reported as absent.
Steps to reproduce
- Run the gateway in a container started with
--cgroupns=private and a cgroup
path other than /.
- Query the
x-medkit-procfs data for the process.
- Compare the reported CPU and memory limits with the ones set on the container.
Expected behavior
Container CPU and memory limits are reported on cgroup v1 and v2, and under both
cgroupns=host and cgroupns=private.
Actual behavior
On cgroup v1 the read fails and no limits are reported. Under cgroupns=private
with a non-root path the limit files are not found and the limits are reported as
absent, which is indistinguishable from an unlimited container.
Environment
- ros2_medkit version: 0.6.0
- ROS 2 distro: all
- OS: any Linux host; the v1 case needs a host without unified cgroups
Additional information
Suggested fix:
- Try the bare path
/sys/fs/cgroup/<file> first, and fall back to the joined
path only if that misses. That covers both namespace modes without detecting
which one is in use.
- Parse the v1 line format as well, and read
cpu.cfs_quota_us divided by
cpu.cfs_period_us for the CPU limit and memory.limit_in_bytes for memory.
- Reporting "no limit" when the file could not be read hides the failure. It
would be better to distinguish "unlimited" from "could not read".
Note that sched_getaffinity() is the only source that reflects --cpuset-cpus.
A quota read alone does not see it, so a caller that wants the effective CPU
budget needs both.
Bug report
cgroup_readerinros2_medkit_linux_introspectionreports container limitsonly for one of the three common cgroup layouts. In the other two it either
fails completely or silently returns nothing.
Both problems are in
src/ros2_medkit_discovery_plugins/ros2_medkit_linux_introspection/src/linux_utils/cgroup_reader.cpp.1. cgroup v1 is not handled.
read_cgroup_path()only matches the cgroup v2 line format:On a pure cgroup v1 host every line has the form
<id>:<controllers>:<path>, sono line matches, the function returns an empty string, and
read_cgroup_info()gives up.
2. The filesystem path is built for
cgroupns=hostonly.This assumes
/proc/self/cgroupreports a path like/docker/<id>, which is thecase with
cgroupns=host. Withcgroupns=private, which is the default incurrent Docker, the container sees its own cgroup mounted directly at
/sys/fs/cgroupand the reported path is usually/. The concatenation thengives
/sys/fs/cgroup//cpu.max, which happens to resolve. Any private namespacewith a path other than
/builds a path that does not exist, and the limits arereported as absent.
Steps to reproduce
--cgroupns=privateand a cgrouppath other than
/.x-medkit-procfsdata for the process.Expected behavior
Container CPU and memory limits are reported on cgroup v1 and v2, and under both
cgroupns=hostandcgroupns=private.Actual behavior
On cgroup v1 the read fails and no limits are reported. Under
cgroupns=privatewith a non-root path the limit files are not found and the limits are reported as
absent, which is indistinguishable from an unlimited container.
Environment
Additional information
Suggested fix:
/sys/fs/cgroup/<file>first, and fall back to the joinedpath only if that misses. That covers both namespace modes without detecting
which one is in use.
cpu.cfs_quota_usdivided bycpu.cfs_period_usfor the CPU limit andmemory.limit_in_bytesfor memory.would be better to distinguish "unlimited" from "could not read".
Note that
sched_getaffinity()is the only source that reflects--cpuset-cpus.A quota read alone does not see it, so a caller that wants the effective CPU
budget needs both.