Skip to content

Conversation

@sonodima
Copy link
Contributor

@sonodima sonodima commented Dec 23, 2023

Fixes #52860.

The OSX ProcessManager has been updated to extract the process name from its path, rather than relying on the 15-character-limited pbi_comm.

This change improves GetProcessByName, allowing the specification of the full process name for lookup. Additionally, Process.ProcessName now returns the full process name, aligning with the behavior of OSX's Activity Monitor.

Moreover, this update enables the retrieval of process names for which we lack privileges. For example, we can now obtain the pid and other basic information of the launchd process without elevation.

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Dec 23, 2023
@sonodima sonodima marked this pull request as ready for review December 23, 2023 10:01
@ghost
Copy link

ghost commented Dec 23, 2023

Tagging subscribers to this area: @dotnet/area-system-diagnostics-process
See info in area-owners.md if you want to be subscribed.

Issue Details

The OSX ProcessManager has been updated to extract the process name from its path, rather than relying on the 15-character-limited pbi_comm.

This change improves GetProcessByName, allowing the specification of the full process name for lookup. Additionally, Process.ProcessName now returns the full process name, aligning with the behavior of OSX's Activity Monitor.

Moreover, this update enables the retrieval of process names for which we lack privileges. For example, we can now obtain the pid and other basic information of the launchd process without elevation.

Author: sonodima
Assignees: -
Labels:

area-System.Diagnostics.Process, community-contribution

Milestone: -

@sonodima

This comment was marked as off-topic.

@huoyaoyuan
Copy link
Member

Can you provide more detailed code snippet to demonstrate what problem it solves? Can there be unit test added?

@sonodima
Copy link
Contributor Author

sonodima commented Dec 25, 2023

Can you provide more detailed code snippet to demonstrate what problem it solves? Can there be unit test added?

Here's a simple example: (use a project name with length greater than 15 characters)

using System.Diagnostics;

Process process = Process.GetCurrentProcess();
Console.WriteLine(process.ProcessName);

In this scenario, if the name of the current process exceeds 15 characters, it will be truncated.

using System.Diagnostics;

Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
    Console.WriteLine($"{process.Id} - {process.ProcessName}");
}

This code results in numerous system processes having an empty ProcessName due to limitations in retrieving process infos. Furthermore, the names that are available are all truncated to 15 characters.

This limitation also affects the GetProcessesByName method. For example, to get the PID of the MTLCompilerService process:

using System.Diagnostics;

Process[] processes = Process.GetProcessesByName("MTLCompilerService");
Console.WriteLine(processes.Length); // This will be 0, even if the process is running, due to name truncation

processes = Process.GetProcessesByName("MTLCompilerServ");
Console.WriteLine(processes.Length); // This will be greater than 0 if MTLCompilerService is running

However, this approach introduces uncertainty. If two processes share the same prefix but have different suffixes, it's challenging to selectively identify one over the other.

using System.Diagnostics;

// Attempting to use "Bitwig Plug-in Host ARM64" returns 0 results due to truncation
Process[] armProcesses = Process.GetProcessesByName("Bitwig Plug-in ");
// Process[] intelProcesses = Process.GetProcessByName("Bitwig Plug-in "); ???

// How do we distinguish between ARM64 and X64 versions if both are present?
// We would again need to resort to manually filtering by filename, which is inconvenient

The GetProcessesByName method has improved because it can now retrieve PIDs of processes that would typically require elevation.
While we can't perform extensive operations on these processes without proper privileges, being able to find them and get their PIDs is better than nothing.

Regarding unit tests, it's challenging to test this functionality.
Running GetCurrentProcess during a test returns the process name as dotnet, which is consistent with the previous behaviour.
We could attempt to find a system process that is always running and has a name longer than 15 characters, but this depends on macOS not changing such a process in the future, so I'm not sure how I feel about that.

More of this was discussed in #52860 and #30909

@MichalPetryka
Copy link
Contributor

Regarding unit tests, it's challenging to test this functionality.
Running GetCurrentProcess during a test returns the process name as dotnet, which is consistent with the previous behaviour.
We could attempt to find a system process that is always running and has a name longer than 15 characters, but this depends on macOS not changing such a process in the future, so I'm not sure how I feel about that.

For the 15 character limitation, the test could create a new process with such name and check that and for the elevated checks, I think that iterating on all the processes on the machine will be the best option for that.

@am11
Copy link
Member

am11 commented Dec 27, 2023

There is an existing test skipped on OSX and MacCatalyst:

[ActiveIssue("https://github.com/dotnet/runtime/issues/29330", TestPlatforms.OSX)]
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/52852", TestPlatforms.MacCatalyst)]

Just delete line 2265 and 2267 from that file.

@sonodima
Copy link
Contributor Author

There is an existing test skipped on OSX and MacCatalyst:

[ActiveIssue("https://github.com/dotnet/runtime/issues/29330", TestPlatforms.OSX)]
[Fact]
[ActiveIssue("https://github.com/dotnet/runtime/issues/52852", TestPlatforms.MacCatalyst)]

Just delete line 2265 and 2267 from that file.

I'm having a few issues getting this test to function correctly in its current form.
I've observed that if the /bin/sleep command is relocated to a different path, it stops working, even after I remove the extended attributes and re-sign the binary.

Attempting to use a temporary script with the long name to execute the sleep command doesn't seem to resolve the issue either. This is because the process that gets executed is named bash, not the script's name.

Comment on lines 42 to 43
// Fallback to empty string if the process name could not be retrieved
processName ??= "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we fallback to pbi_comm if GetProcPath fails instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we could fall back to pbi_comm if we have the proc_taskallinfo, and otherwise just fall back to the empty string again.

I'll work on these changes 👍

@jozkee
Copy link
Member

jozkee commented Jan 25, 2024

I've observed that if the /bin/sleep command is relocated to a different path, it stops working, even after I remove the extended attributes and re-sign the binary.

I'm seeing this problem too on Sonoma. I also tried removing the signature (codesign --remove-signature ./sleep-copy) but no luck. @dotnet/area-system-diagnostics-process @wfurt any ideas?

@sonodima
Copy link
Contributor Author

I'm seeing this problem too on Sonoma.

I just tried this again but with System Integrity Protection disabled and now the copied binary works correctly

@jozkee
Copy link
Member

jozkee commented Jan 25, 2024

I just tried this again but with System Integrity Protection disabled and now the copied binary works correctly

Yes but I don't know if the OSX machines in CI run without SIP. cc @dotnet/area-infrastructure-libraries @dotnet/dnceng.

Copy link
Member

@jozkee jozkee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks. We should address re-enabling the OSX test before 9.0 ships (#29330).

@jozkee jozkee merged commit 69f4f85 into dotnet:main Jan 29, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Feb 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.Diagnostics.Process.GetProcesses() returns truncated 15 char string on macOS

5 participants