fix(container): use lstrip("/") in inode path join and try cgroup path first#950
Open
vlad-scherbich wants to merge 2 commits into
Open
fix(container): use lstrip("/") in inode path join and try cgroup path first#950vlad-scherbich wants to merge 2 commits into
vlad-scherbich wants to merge 2 commits into
Conversation
…h first
Two bugs in Cgroup container ID resolution:
1. _get_cgroup_from_inode used `!= "/"` to guard against the root case,
but os.path.join silently drops all preceding components when it sees an
absolute path segment. Any non-root absolute node path (e.g.
"/system.slice/docker-deadbeef.scope") caused the cgroup mount prefix
to be discarded, so os.stat was called on the wrong path.
Fix: strip the leading slash with lstrip("/") before joining.
2. __init__ skipped _read_cgroup_path entirely when the process was not in
the host cgroup namespace. Containers with a private cgroup namespace
but a still-parseable cgroup v1 path (uncommon but valid) were
silently routed to the inode fallback.
Fix: always attempt _read_cgroup_path first; only fall back to the
inode approach when the path yields nothing AND the process is not in
the host cgroup namespace.
Also wrap _get_cgroup_from_inode in a try/except so transient OS errors
(e.g. a missing cgroup mount) surface as None rather than a propagating
exception, consistent with the defensive style already used in
_read_cgroup_path.
|
…r, and inode fallback
- Parametrized: add K8s systemd slice/scope hierarchy (docker-{id}.scope leaf)
- Parametrized: non-containerized Linux case already covered
- _is_host_cgroup_namespace: add 4 unit tests (missing file, matching inode,
non-matching inode, exception swallowed)
- _get_cgroup_from_inode: add test for cgroup v1 memory inode=0 falling
through to the cgroup v2 (CGROUPV2_BASE_CONTROLLER="") entry
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two bugs in
Cgroupcontainer ID resolution indatadog/dogstatsd/container.py:Bug 1 —
_get_cgroup_from_inode: absolute cgroup node path drops mount prefixos.path.joinsilently discards all preceding components when it encounters anabsolute path segment. The previous guard only handled the root case (
!= "/"),so any non-root absolute node path (e.g.
"/system.slice/docker-deadbeef.scope")caused the cgroup mount prefix to be lost:
Fix: strip the leading slash with
lstrip("/")before joining.Bug 2 —
__init__: cgroup path skipped when not in host cgroup namespaceThe original logic used
_is_host_cgroup_namespace()as a gate: if False, it wentstraight to the inode fallback and never tried to parse the cgroup path. Containers
with a private cgroup namespace but a still-parseable cgroup v1 path (a valid
configuration) were silently routed to inode lookup even though a container ID was
available in the path.
Fix: always attempt
_read_cgroup_pathfirst; only fall back to_get_cgroup_from_inodewhen the path yields
Noneand the process is not in the host cgroup namespace.Bonus: defensive
try/exceptin_get_cgroup_from_inodeWrap the inode lookup in a
try/exceptso transient OS errors (e.g. missing cgroupmount) surface as
Nonerather than a propagating exception — consistent with thedefensive style already used in
_read_cgroup_path.Tests
test_container_id_inodeupdated to expect twoopencalls (the new_read_cgroup_pathcall + the inode path call) and now assertscall_count == 2.test_container_id_inode_absolute_node_path(new): verifies thelstripfix by exercising a cgroup v2 entry with a non-root absolute node path.test_container_id_cgroup_path_takes_priority_over_inode(new): verifies Bug 2 is fixed — cgroup path wins over inode when the process is not in the host namespace.Context
These bugs were discovered while backporting cgroup v2 origin-detection support into
dd-trace-py, where
container.pyisvendored. The fixes were validated there first and are contributed back upstream.