-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Process.Linux: handle when /proc and the process pid namespace don't match. #100076
Conversation
…match. Normally the '/proc' filesystem uses the same pid namespace as the process. With rootless containers, it may happen that these pid namespaces do not match because the container doesn't have permissions to change '/proc' but it can create a new pid namespace. When that happens, the numeric ids used by the /proc filesystem no longer match with the process pid namespace. We can still access information for the current process using '/proc/self'. For other processes, we can't map pids to the proc pids, which leads to reading information for non-existing/wrong/inaccessible processes.
Tagging subscribers to this area: @dotnet/area-system-diagnostics-process |
To reproduces the issue without containers, you can run In that environment you can run a program like:
When running this, sometimes this will print out a value, sometimes throw In all cases, it is using information from |
@dotnet/area-system-diagnostics-process can you take a look? Though it is not a common scenario, I think it's valuable we make .NET behave correct because it can occur in containers and CI. A user can not fix it and diagnosing the root cause may also be a challenge for them. |
For "self" case, we could short-circuit to |
To get the current process pid we don't use |
We're adding |
@dotnet/area-system-diagnostics-process ptal. |
1 similar comment
@dotnet/area-system-diagnostics-process ptal. |
@jeffhandley @adamsitnik can you take a look at this PR please? |
@jeffhandley @adamsitnik can you take a look? I assume the review is slow because this is a niche case. I looked into this due to a support case. The root cause was hard to diagnose for the end-user, and they could not work around it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay. LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM, but please answer my question before I hit the merge button.
And once again big thanks for your help @tmds and apologies for the delays in my areas (I was 100% focused on the BinaryFormatter
removal effort)
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Linux.cs
Outdated
Show resolved
Hide resolved
{ | ||
procSelfPid = pid; | ||
} | ||
Debug.Assert(procSelfPid.HasValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Debug.Assert(procSelfPid.HasValue)
assumes that the value will be always present, but the condition below does not follow this assumption and in such case returns 1 ('/proc' and the process pid namespace match).
Why is that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's handling the unexpected (should never happen) case where we were unable to determine the proc fs pid for self.
@adamsitnik this should be good to merge. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thank you @tmds !
I need to close and re-open the PR so the CI can re-run the failed legs. |
@@ -8,6 +8,6 @@ namespace System | |||
public static partial class Environment | |||
{ | |||
public static long WorkingSet => | |||
(long)(Interop.procfs.TryReadProcessStatusInfo(ProcessId, out Interop.procfs.ProcessStatusInfo status) ? status.ResidentSetSize : 0); | |||
(long)(Interop.procfs.TryReadProcessStatusInfo(Interop.procfs.ProcPid.Self, out Interop.procfs.ProcessStatusInfo status) ? status.ResidentSetSize : 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This breaks the build on illumos. Was this intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I assume the fix is straight forward?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I will push it to my ongoing branch #105178. Was checking if you had other plans for it, I'll just revert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Normally the '/proc' filesystem uses the same pid namespace as the process. With rootless containers, it may happen that these pid namespaces do not match because the container doesn't have permissions to change '/proc' but it can create a new pid namespace.
When that happens, the numeric ids used by the /proc filesystem no longer match with the process pid namespace. We can still access information for the current process using '/proc/self'. For other processes, we can't map pids to the proc pids, which leads to reading information for non-existing/wrong/inaccessible processes.
Closes #99887.
@dotnet/area-system-diagnostics-process @stephentoub ptal.
cc @omajid