From da9e2e681ab8cea29f140a5f1b29a1c4b7fb2b14 Mon Sep 17 00:00:00 2001 From: sonodima Date: Sat, 23 Dec 2023 01:46:22 +0100 Subject: [PATCH 1/3] Obtain ProcessName from proc_pidpath on OSX --- .../System/Diagnostics/ProcessManager.OSX.cs | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs index 92c16de7217abd..41d4ab423e367e 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs @@ -32,15 +32,30 @@ private static string GetProcPath(int processId) Interop.libproc.proc_taskallinfo? info = Interop.libproc.GetProcessInfoById(pid); if (info.HasValue) { - // Set the values we have; all the other values don't have meaning or don't exist on OSX - Interop.libproc.proc_taskallinfo temp = info.Value; - string processName; - unsafe { processName = Marshal.PtrToStringUTF8(new IntPtr(temp.pbsd.pbi_comm))!; } + string? processName = null; + + try + { + // Extract the process name from its path, because other alternatives such as + // reading proc_taskallinfo.pbsd.pbi_comm are limited in length + string processPath = GetProcPath(pid); + processName = Path.GetFileName(processPath); + } + catch + { + // Ignored + } + + // Fallback to empty string if the process name could not be retrieved + processName ??= ""; + if (!string.IsNullOrEmpty(processNameFilter) && !string.Equals(processName, processNameFilter, StringComparison.OrdinalIgnoreCase)) { return null; } + // Set the values we have; all the other values don't have meaning or don't exist on OSX + Interop.libproc.proc_taskallinfo temp = info.Value; procInfo = new ProcessInfo() { ProcessId = pid, From 0ffaceff4fe3afe402e70d2fe3bb9f675aee6994 Mon Sep 17 00:00:00 2001 From: sonodima Date: Sat, 23 Dec 2023 10:51:14 +0100 Subject: [PATCH 2/3] Improve ProcessName retrieval without elevation on OSX --- .../System/Diagnostics/ProcessManager.OSX.cs | 74 ++++++++----------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs index 41d4ab423e367e..ff8c8017c78a11 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs @@ -25,58 +25,44 @@ private static string GetProcPath(int processId) // Negative PIDs aren't valid ArgumentOutOfRangeException.ThrowIfNegative(pid); - ProcessInfo procInfo; + string? processName = null; - // Try to get the task info. This can fail if the user permissions don't permit - // this user context to query the specified process - Interop.libproc.proc_taskallinfo? info = Interop.libproc.GetProcessInfoById(pid); - if (info.HasValue) + try { - string? processName = null; + // Extract the process name from its path, because other alternatives such as + // reading proc_taskallinfo.pbsd.pbi_comm are limited in length + string processPath = GetProcPath(pid); + processName = Path.GetFileName(processPath); + } + catch + { + // Ignored + } - try - { - // Extract the process name from its path, because other alternatives such as - // reading proc_taskallinfo.pbsd.pbi_comm are limited in length - string processPath = GetProcPath(pid); - processName = Path.GetFileName(processPath); - } - catch - { - // Ignored - } + // Fallback to empty string if the process name could not be retrieved + processName ??= ""; - // Fallback to empty string if the process name could not be retrieved - processName ??= ""; + if (!string.IsNullOrEmpty(processNameFilter) && !string.Equals(processName, processNameFilter, StringComparison.OrdinalIgnoreCase)) + { + return null; + } - if (!string.IsNullOrEmpty(processNameFilter) && !string.Equals(processName, processNameFilter, StringComparison.OrdinalIgnoreCase)) - { - return null; - } + var procInfo = new ProcessInfo() + { + ProcessId = pid, + ProcessName = processName, + }; + // Try to get the task info. This can fail if the user permissions don't permit + // this user context to query the specified process + Interop.libproc.proc_taskallinfo? info = Interop.libproc.GetProcessInfoById(pid); + if (info.HasValue) + { // Set the values we have; all the other values don't have meaning or don't exist on OSX Interop.libproc.proc_taskallinfo temp = info.Value; - procInfo = new ProcessInfo() - { - ProcessId = pid, - ProcessName = processName, - BasePriority = temp.pbsd.pbi_nice, - VirtualBytes = (long)temp.ptinfo.pti_virtual_size, - WorkingSet = (long)temp.ptinfo.pti_resident_size, - }; - } - else if (string.IsNullOrEmpty(processNameFilter)) - { - procInfo = new ProcessInfo() - { - ProcessId = pid, - }; - } - else - { - // We couldn't get process information but we only want to return a process that - // matches the specified name, so consider this process not a match. - return null; + procInfo.BasePriority = temp.pbsd.pbi_nice; + procInfo.VirtualBytes = (long)temp.ptinfo.pti_virtual_size; + procInfo.WorkingSet = (long)temp.ptinfo.pti_resident_size; } // Get the sessionId for the given pid, getsid returns -1 on error From a67fd560816688a84f9e1c9cb7c57e5238ae2ab6 Mon Sep 17 00:00:00 2001 From: sonodima Date: Fri, 26 Jan 2024 16:04:53 +0100 Subject: [PATCH 3/3] Use the ProcessName from pbi_comm if proc_pidpath fails on OSX --- .../System/Diagnostics/ProcessManager.OSX.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs index ff8c8017c78a11..0d4b7fccf1e7c3 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs @@ -39,7 +39,19 @@ private static string GetProcPath(int processId) // Ignored } - // Fallback to empty string if the process name could not be retrieved + // Try to get the task info. This can fail if the user permissions don't permit + // this user context to query the specified process + Interop.libproc.proc_taskallinfo? info = Interop.libproc.GetProcessInfoById(pid); + + // If we could not get the process name from its path, attempt to use the old 15-char + // limited process name + if (string.IsNullOrEmpty(processName) && info != null) + { + Interop.libproc.proc_taskallinfo temp = info.Value; + unsafe { processName = Marshal.PtrToStringUTF8(new IntPtr(temp.pbsd.pbi_comm)); } + } + + // Fallback to empty string if the process name could not be retrieved in any way processName ??= ""; if (!string.IsNullOrEmpty(processNameFilter) && !string.Equals(processName, processNameFilter, StringComparison.OrdinalIgnoreCase)) @@ -53,9 +65,6 @@ private static string GetProcPath(int processId) ProcessName = processName, }; - // Try to get the task info. This can fail if the user permissions don't permit - // this user context to query the specified process - Interop.libproc.proc_taskallinfo? info = Interop.libproc.GetProcessInfoById(pid); if (info.HasValue) { // Set the values we have; all the other values don't have meaning or don't exist on OSX