diff --git a/core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java b/core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java index a2cf1891bad..43ef51658b7 100644 --- a/core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java +++ b/core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java @@ -187,9 +187,6 @@ public class OsProbe { return lines.get(0); } - // pattern for lines in /proc/self/cgroup - private static final Pattern CONTROL_GROUP_PATTERN = Pattern.compile("\\d+:([^:]+):(/.*)"); - // this property is to support a hack to workaround an issue with Docker containers mounting the cgroups hierarchy inconsistently with // respect to /proc/self/cgroup; for Docker containers this should be set to "/" private static final String CONTROL_GROUPS_HIERARCHY_OVERRIDE = System.getProperty("es.cgroups.hierarchy.override"); @@ -205,23 +202,29 @@ public class OsProbe { final List lines = readProcSelfCgroup(); final Map controllerMap = new HashMap<>(); for (final String line : lines) { - final Matcher matcher = CONTROL_GROUP_PATTERN.matcher(line); - // Matcher#matches must be invoked as matching is lazy; this can not happen in an assert as assertions might not be enabled - final boolean matches = matcher.matches(); - assert matches : line; - // at this point we have captured the subsystems and the control group - final String[] controllers = matcher.group(1).split(","); + /* + * The virtual file /proc/self/cgroup lists the control groups that the Elasticsearch process is a member of. Each line contains + * three colon-separated fields of the form hierarchy-ID:subsystem-list:cgroup-path. For cgroups version 1 hierarchies, the + * subsystem-list is a comma-separated list of subsystems. The subsystem-list can be empty if the hierarchy represents a cgroups + * version 2 hierarchy. For cgroups version 1 + */ + final String[] fields = line.split(":"); + assert fields.length == 3; + final String[] controllers = fields[1].split(","); for (final String controller : controllers) { + final String controlGroupPath; if (CONTROL_GROUPS_HIERARCHY_OVERRIDE != null) { /* * Docker violates the relationship between /proc/self/cgroup and the /sys/fs/cgroup hierarchy. It's possible that this * will be fixed in future versions of Docker with cgroup namespaces, but this requires modern kernels. Thus, we provide * an undocumented hack for overriding the control group path. Do not rely on this hack, it will be removed. */ - controllerMap.put(controller, CONTROL_GROUPS_HIERARCHY_OVERRIDE); + controlGroupPath = CONTROL_GROUPS_HIERARCHY_OVERRIDE; } else { - controllerMap.put(controller, matcher.group(2)); + controlGroupPath = fields[2]; } + final String previous = controllerMap.put(controller, controlGroupPath); + assert previous == null; } } return controllerMap; diff --git a/core/src/test/java/org/elasticsearch/monitor/os/OsProbeTests.java b/core/src/test/java/org/elasticsearch/monitor/os/OsProbeTests.java index c987e44c108..4cceddb6a96 100644 --- a/core/src/test/java/org/elasticsearch/monitor/os/OsProbeTests.java +++ b/core/src/test/java/org/elasticsearch/monitor/os/OsProbeTests.java @@ -155,16 +155,17 @@ public class OsProbeTests extends ESTestCase { @Override List readProcSelfCgroup() { return Arrays.asList( - "10:freezer:/", - "9:net_cls,net_prio:/", - "8:pids:/", - "7:blkio:/", - "6:memory:/", - "5:devices:/user.slice", - "4:hugetlb:/", - "3:perf_event:/", - "2:cpu,cpuacct,cpuset:/" + hierarchy, - "1:name=systemd:/user.slice/user-1000.slice/session-2359.scope"); + "10:freezer:/", + "9:net_cls,net_prio:/", + "8:pids:/", + "7:blkio:/", + "6:memory:/", + "5:devices:/user.slice", + "4:hugetlb:/", + "3:perf_event:/", + "2:cpu,cpuacct,cpuset:/" + hierarchy, + "1:name=systemd:/user.slice/user-1000.slice/session-2359.scope", + "0::/cgroup2"); } @Override