Skip to content

Commit

Permalink
Handle existence of cgroup version 2 hierarchy
Browse files Browse the repository at this point in the history
When parsing the control groups to which the Elasticsearch process
belongs, we extract a map from subsystems to paths by parsing
/proc/self/cgroup. This file contains colon-delimited entries of the
form hierarchy-ID:subsystem-list:cgroup-path. For control group version
1 hierarchies, the subsystem-list is a comma-delimited list of the
subsystems for that hierarchy. For control group version 2 hierarchies
(which can only exist on Linux kernels since version 4.5), the
subsystem-list is an empty string. The previous parsing of
/proc/self/cgroup incorrectly accounted for this possibility (a +
instead of a * in a regular expression). This commit addresses this
issue, adds a test case that covers this possibility, and simplifies the
code that parses /proc/self/cgroup.

Relates #23493
  • Loading branch information
jasontedor committed Mar 6, 2017
1 parent 47ae063 commit 25595a0
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 21 deletions.
25 changes: 14 additions & 11 deletions core/src/main/java/org/elasticsearch/monitor/os/OsProbe.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,6 @@ private String readSingleLine(final Path path) throws IOException {
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");
Expand All @@ -205,23 +202,29 @@ private Map<String, String> getControlGroups() throws IOException {
final List<String> lines = readProcSelfCgroup();
final Map<String, String> 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;
Expand Down
21 changes: 11 additions & 10 deletions core/src/test/java/org/elasticsearch/monitor/os/OsProbeTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,16 +155,17 @@ public void testCgroupProbe() {
@Override
List<String> 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
Expand Down

0 comments on commit 25595a0

Please sign in to comment.