internal static ProcessInfo CreateProcessInfo(Interop.procfs.ParsedStat procFsStat, ReusableTextReader reusableReader)
{
int pid = procFsStat.pid;
var pi = new ProcessInfo()
{
ProcessId = pid,
ProcessName = procFsStat.comm,
BasePriority = (int)procFsStat.nice,
VirtualBytes = (long)procFsStat.vsize,
WorkingSet = procFsStat.rss * Environment.SystemPageSize,
SessionId = procFsStat.session,
// We don't currently fill in the other values.
// A few of these could probably be filled in from getrusage,
// but only for the current process or its children, not for
// arbitrary other processes.
};
// Then read through /proc/pid/task/ to find each thread in the process...
string tasksDir = Interop.procfs.GetTaskDirectoryPathForProcess(pid);
try
{
foreach (string taskDir in Directory.EnumerateDirectories(tasksDir))
{
// ...and read its associated /proc/pid/task/tid/stat file to create a ThreadInfo
string dirName = Path.GetFileName(taskDir);
int tid;
Interop.procfs.ParsedStat stat;
if (int.TryParse(dirName, NumberStyles.Integer, CultureInfo.InvariantCulture, out tid) &&
Interop.procfs.TryReadStatFile(pid, tid, out stat, reusableReader))
{
unsafe
{
pi._threadInfoList.Add(new ThreadInfo()
{
_processId = pid,
_threadId = (ulong)tid,
_basePriority = pi.BasePriority,
_currentPriority = (int)stat.nice,
_startAddress = IntPtr.Zero,
_threadState = ProcFsStateToThreadState(stat.state),
_threadWaitReason = ThreadWaitReason.Unknown
});
}
}
}
}
catch (IOException)
{
// Between the time that we get an ID and the time that we try to read the associated
// directories and files in procfs, the process could be gone.
}
// Finally return what we've built up
return pi;
}