Open am11 opened 3 months ago
Tagging subscribers to this area: @dotnet/area-system-serviceprocess See info in area-owners.md if you want to be subscribed.
Tagging subscribers to this area: @dotnet/area-system-diagnostics-process See info in area-owners.md if you want to be subscribed.
Triage: If it's possible to provide more information rather than just throw, we should improve our implementation and just do that. Since I have no free cycles right now the best I can do is to mark it as "help wanted".
The current design is that ProcessStartInfo
gathers the information needed to start a process, and information about a running process is retrieved through properties of the Process
class. I think we should stick to those responsibilities.
@am11 what information do you need that is currently not accessible through Process
properties. I assume it is mostly about arguments? What could the API look like on the Process
class?
ps: there is a macOS-sepcific quirk that we can use process.MainModule.FullName to find the path, but MainModule is null for "not owned by us" process on Linux and FreeBSD
Should/can we address this?
The current design is that
ProcessStartInfo
gathers the information needed to start a process, and information about a running process is retrieved through properties of theProcess
class. I think we should stick to those responsibilities.
ProcessStartInfo StartInfo
is also a property on Process
class. Eagerly throwing exception where OS and other tools have no problem, is not a sound design worth defending. I think if we can improve it, we should.
Currently ProcessStartInfo
works as an argument list for Start
and it can only be retrieved if the process was started by the Process
instance. The semantics are clear.
I think it would be good to understand what information users are looking for and how well we can support it on different OSes. Then we can know if ProcessStartInfo
is a good fit.
I think it would be good to understand what information users are looking for and how well we can support it on different OSes. Then we can know if
ProcessStartInfo
is a good fit.
I was seeking the name and arguments of external process (pid:1 init
in my case). If certain information is inaccessible on a platform, the corresponding API should throw an exception, as it currently does. This issue might also occur if the user is running the app in a resource-restricted environment on a platform that typically supports accessing the information. Therefore, handling this at runtime on a best-effort basis is the appropriate approach.
ps: there is a macOS-sepcific quirk that we can use process.MainModule.FullName to find the path, but MainModule is null for "not owned by us" process on Linux and FreeBSD
If Linux would behave similar to macOS, you'd be able to do what you need?
Yup, it seems ps ax -o pid,comm,args
is returning the expected values so if we can make it return the process path and arguments (when possible) that would be enough. macOS also return process path and arguments, but we currently throw from StartInfo.Arguments
:
$ uname -a
Darwin 87-92-225-103.rev.dnainternet.fi 23.5.0 Darwin Kernel Version 23.5.0: Wed May 1 20:12:58 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6000 arm64
$ ps ax -o pid,comm,args | while read pid comm args; do
if [ "$pid" = 1 ]; then
printf '%s\t%s\t%s\n' "$pid" "$comm" "$args"
fi
done
1 /sbin/launchd /sbin/launchd
vs.
$ cat Program.cs
using System.Diagnostics;
Process initProcess = Process.GetProcessById(1);
Console.WriteLine($"ProcessPath: {initProcess.MainModule?.FileName}");
Console.WriteLine($"ArgumentsLength: {initProcess.StartInfo.Arguments.Length}");
$ dotnet run
ProcessPath: /sbin/launchd
Unhandled exception. System.InvalidOperationException: Process was not started by this object, so requested information cannot be determined.
at System.Diagnostics.Process.get_StartInfo()
at Program.<Main>$(String[] args) in /Users/am11/projects/startinfo-shenanigans/Program.cs:line 5
Currently, this API throws if the process is not self or a child of current process.
System.InvalidOperationException: Process was not started by this object, so requested information cannot be determined.
Other tools, such as
ps(1)
, provide information about the process in a "best effort" manner, e.g.gives info about the init process on Linux, macOS and FreeBSD alike, regardless of the current user privileges. In contrast, while this program will output the process name of the non-self, non-children processes:
we cannot get the process path or arguments which
ps(1)
offers.ps: there is a macOS-sepcific quirk that we can use
process.MainModule.FullName
to find the path, but MainModule is null for "not owned by us" process on Linux and FreeBSDFWIW, I was trying to make this implementation of UnixInitSystem detection robust for case where multiple init systems are installed (and one of them is active); using
Process
:guess I can shell out to
ps(1)
directly for this.