Exemplo n.º 1
0
        internal static bool TryReadStatFile(int pid, out ParsedStat result, ReusableTextReader reusableReader)
        {
            bool b = TryParseStatFile(GetStatFilePathForProcess(pid), out result, reusableReader);

            Debug.Assert(!b || result.pid == pid, "Expected process ID from stat file to match supplied pid");
            return(b);
        }
Exemplo n.º 2
0
        // -----------------------------
        // ---- PAL layer ends here ----
        // -----------------------------

        /// <summary>
        /// Creates a ProcessInfo from the specified process ID.
        /// </summary>
        internal static ProcessInfo CreateProcessInfo(int pid, ReusableTextReader reusableReader = null)
        {
            reusableReader ??= new ReusableTextReader();
            if (Interop.procfs.TryReadStatFile(pid, out Interop.procfs.ParsedStat stat, reusableReader))
            {
                Interop.procfs.TryReadStatusFile(pid, out Interop.procfs.ParsedStatus status, reusableReader);
                return(CreateProcessInfo(ref stat, ref status, reusableReader));
            }
            return(null);
        }
Exemplo n.º 3
0
        // -----------------------------
        // ---- PAL layer ends here ----
        // -----------------------------

        /// <summary>
        /// Creates a ProcessInfo from the specified process ID.
        /// </summary>
        internal static ProcessInfo CreateProcessInfo(int pid, ReusableTextReader reusableReader = null)
        {
            if (reusableReader == null)
            {
                reusableReader = new ReusableTextReader();
            }

            Interop.procfs.ParsedStat stat;
            return(Interop.procfs.TryReadStatFile(pid, out stat, reusableReader) ?
                   CreateProcessInfo(stat, reusableReader) :
                   null);
        }
Exemplo n.º 4
0
 private static bool TryReadFile(string filePath, ReusableTextReader reusableReader, out string fileContents)
 {
     try
     {
         using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, useAsync: false))
         {
             fileContents = reusableReader.ReadAllText(fileStream);
             return(true);
         }
     }
     catch (IOException)
     {
         fileContents = null;
         return(false);
     }
 }
Exemplo n.º 5
0
        /// <summary>Gets process infos for each process on the specified machine.</summary>
        /// <param name="machineName">The target machine.</param>
        /// <returns>An array of process infos, one per found process.</returns>
        public static ProcessInfo[] GetProcessInfos(string machineName)
        {
            ThrowIfRemoteMachine(machineName);
            int[] procIds = GetProcessIds(machineName);

            // Iterate through all process IDs to load information about each process
            var reusableReader = new ReusableTextReader();
            var processes      = new List <ProcessInfo>(procIds.Length);

            foreach (int pid in procIds)
            {
                ProcessInfo pi = CreateProcessInfo(pid, reusableReader);
                if (pi != null)
                {
                    processes.Add(pi);
                }
            }

            return(processes.ToArray());
        }
Exemplo n.º 6
0
        /// <summary>
        /// Creates an array of <see cref="Process"/> components that are associated with process resources on a
        /// remote computer. These process resources share the specified process name.
        /// </summary>
        public static Process[] GetProcessesByName(string processName, string machineName)
        {
            ProcessManager.ThrowIfRemoteMachine(machineName);
            if (processName == null)
            {
                processName = string.Empty;
            }

            var reusableReader = new ReusableTextReader();
            var processes      = new List <Process>();

            foreach (int pid in ProcessManager.EnumerateProcessIds())
            {
                if (string.Equals(processName, Process.GetProcessName(pid), StringComparison.OrdinalIgnoreCase))
                {
                    ProcessInfo processInfo = ProcessManager.CreateProcessInfo(pid, reusableReader, processName);
                    processes.Add(new Process(machineName, false, processInfo.ProcessId, processInfo));
                }
            }

            return(processes.ToArray());
        }
Exemplo n.º 7
0
        /// <summary>
        /// Creates an array of <see cref="Process"/> components that are associated with process resources on a
        /// remote computer. These process resources share the specified process name.
        /// </summary>
        public static Process[] GetProcessesByName(string?processName, string machineName)
        {
            ProcessManager.ThrowIfRemoteMachine(machineName);
            if (processName == null)
            {
                processName = string.Empty;
            }

            var reusableReader = new ReusableTextReader();
            var processes      = new List <Process>();

            foreach (int pid in ProcessManager.EnumerateProcessIds())
            {
                if (Interop.procfs.TryReadStatFile(pid, out Interop.procfs.ParsedStat parsedStat, reusableReader) &&
                    string.Equals(processName, Process.GetUntruncatedProcessName(ref parsedStat), StringComparison.OrdinalIgnoreCase) &&
                    Interop.procfs.TryReadStatusFile(pid, out Interop.procfs.ParsedStatus parsedStatus, reusableReader))
                {
                    ProcessInfo processInfo = ProcessManager.CreateProcessInfo(ref parsedStat, ref parsedStatus, reusableReader, processName);
                    processes.Add(new Process(machineName, false, processInfo.ProcessId, processInfo));
                }
            }

            return(processes.ToArray());
        }
Exemplo n.º 8
0
        /// <summary>
        /// Creates a ProcessInfo from the data parsed from a /proc/pid/stat file and the associated tasks directory.
        /// </summary>
        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,
                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))
                    {
                        pi._threadInfoList.Add(new ThreadInfo()
                        {
                            _processId        = pid,
                            _threadId         = (ulong)tid,
                            _basePriority     = pi.BasePriority,
                            _currentPriority  = (int)stat.nice,
                            _startAddress     = (IntPtr)stat.startstack,
                            _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);
        }
Exemplo n.º 9
0
        internal static bool TryParseStatFile(string statFilePath, out ParsedStat result, ReusableTextReader reusableReader)
        {
            string statFileContents;

            try
            {
                using (var source = new FileStream(statFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, useAsync: false))
                {
                    statFileContents = reusableReader.ReadAllText(source);
                }
            }
            catch (IOException)
            {
                // Between the time that we get an ID and the time that we try to read the associated stat
                // file(s), the process could be gone.
                result = default(ParsedStat);
                return(false);
            }

            var parser  = new StringParser(statFileContents, ' ');
            var results = default(ParsedStat);

            results.pid   = parser.ParseNextInt32();
            results.comm  = parser.MoveAndExtractNextInOuterParens();
            results.state = parser.ParseNextChar();
            results.ppid  = parser.ParseNextInt32();
            parser.MoveNextOrFail(); // pgrp
            results.session = parser.ParseNextInt32();
            parser.MoveNextOrFail(); // tty_nr
            parser.MoveNextOrFail(); // tpgid
            parser.MoveNextOrFail(); // flags
            parser.MoveNextOrFail(); // majflt
            parser.MoveNextOrFail(); // cmagflt
            parser.MoveNextOrFail(); // minflt
            parser.MoveNextOrFail(); // cminflt
            results.utime = parser.ParseNextUInt64();
            results.stime = parser.ParseNextUInt64();
            parser.MoveNextOrFail(); // cutime
            parser.MoveNextOrFail(); // cstime
            parser.MoveNextOrFail(); // priority
            results.nice = parser.ParseNextInt64();
            parser.MoveNextOrFail(); // num_threads
            parser.MoveNextOrFail(); // itrealvalue
            results.starttime = parser.ParseNextUInt64();
            results.vsize     = parser.ParseNextUInt64();
            results.rss       = parser.ParseNextInt64();
            results.rsslim    = parser.ParseNextUInt64();

            // The following lines are commented out as there's no need to parse through
            // the rest of the entry (we've gotten all of the data we need).  Should any
            // of these fields be needed in the future, uncomment all of the lines up
            // through and including the one that's needed.  For now, these are being left
            // commented to document what's available in the remainder of the entry.

            //parser.MoveNextOrFail(); // startcode
            //parser.MoveNextOrFail(); // endcode
            //parser.MoveNextOrFail(); // startstack
            //parser.MoveNextOrFail(); // kstkesp
            //parser.MoveNextOrFail(); // kstkeip
            //parser.MoveNextOrFail(); // signal
            //parser.MoveNextOrFail(); // blocked
            //parser.MoveNextOrFail(); // sigignore
            //parser.MoveNextOrFail(); // sigcatch
            //parser.MoveNextOrFail(); // wchan
            //parser.MoveNextOrFail(); // nswap
            //parser.MoveNextOrFail(); // cnswap
            //parser.MoveNextOrFail(); // exit_signal
            //parser.MoveNextOrFail(); // processor
            //parser.MoveNextOrFail(); // rt_priority
            //parser.MoveNextOrFail(); // policy
            //parser.MoveNextOrFail(); // delayacct_blkio_ticks
            //parser.MoveNextOrFail(); // guest_time
            //parser.MoveNextOrFail(); // cguest_time

            result = results;
            return(true);
        }
Exemplo n.º 10
0
        internal static bool TryReadStatFile(int pid, int tid, out ParsedStat result, ReusableTextReader reusableReader)
        {
            bool b = TryParseStatFile(GetStatFilePathForThread(pid, tid), out result, reusableReader);

            //
            // This assert currently fails in the Windows Subsystem For Linux.  See https://github.com/Microsoft/BashOnWindows/issues/967.
            //
            //Debug.Assert(!b || result.pid == tid, "Expected thread ID from stat file to match supplied tid");
            return(b);
        }
Exemplo n.º 11
0
        private static bool TryParseStatFile(string statFilePath, out ParsedStat result, ReusableTextReader reusableReader)
        {
            string statFileContents;

            try
            {
                using (var source = new FileStream(statFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1, useAsync: false))
                {
                    statFileContents = reusableReader.ReadAllText(source);
                }
            }
            catch (IOException)
            {
                // Between the time that we get an ID and the time that we try to read the associated stat
                // file(s), the process could be gone.
                result = default(ParsedStat);
                return(false);
            }

            var parser  = new StringParser(statFileContents, ' ');
            var results = default(ParsedStat);

            results.pid  = parser.ParseNextInt32();
            results.comm = parser.ParseRaw(delegate(string str, ref int startIndex, ref int endIndex)
            {
                if (str[startIndex] == '(')
                {
                    int i;
                    for (i = endIndex; i < str.Length && str[i - 1] != ')'; i++)
                    {
                        ;
                    }
                    if (str[i - 1] == ')')
                    {
                        endIndex = i;
                        return(str.Substring(startIndex + 1, i - startIndex - 2));
                    }
                }
                throw new InvalidDataException();
            });
            results.state = parser.ParseNextChar();
            parser.MoveNextOrFail(); // ppid
            parser.MoveNextOrFail(); // pgrp
            results.session = parser.ParseNextInt32();
            parser.MoveNextOrFail(); // tty_nr
            parser.MoveNextOrFail(); // tpgid
            parser.MoveNextOrFail(); // flags
            parser.MoveNextOrFail(); // majflt
            parser.MoveNextOrFail(); // cmagflt
            parser.MoveNextOrFail(); // minflt
            parser.MoveNextOrFail(); // cminflt
            results.utime = parser.ParseNextUInt64();
            results.stime = parser.ParseNextUInt64();
            parser.MoveNextOrFail(); // cutime
            parser.MoveNextOrFail(); // cstime
            parser.MoveNextOrFail(); // priority
            results.nice = parser.ParseNextInt64();
            parser.MoveNextOrFail(); // num_threads
            parser.MoveNextOrFail(); // itrealvalue
            results.starttime = parser.ParseNextUInt64();
            results.vsize     = parser.ParseNextUInt64();
            results.rss       = parser.ParseNextInt64();
            results.rsslim    = parser.ParseNextUInt64();
            parser.MoveNextOrFail(); // startcode
            parser.MoveNextOrFail(); // endcode
            results.startstack = parser.ParseNextUInt64();
            parser.MoveNextOrFail(); // kstkesp
            parser.MoveNextOrFail(); // kstkeip
            parser.MoveNextOrFail(); // signal
            parser.MoveNextOrFail(); // blocked
            parser.MoveNextOrFail(); // sigignore
            parser.MoveNextOrFail(); // sigcatch
            parser.MoveNextOrFail(); // wchan
            parser.MoveNextOrFail(); // nswap
            parser.MoveNextOrFail(); // cnswap
            parser.MoveNextOrFail(); // exit_signal
            parser.MoveNextOrFail(); // processor
            parser.MoveNextOrFail(); // rt_priority
            parser.MoveNextOrFail(); // policy
            parser.MoveNextOrFail(); // delayacct_blkio_ticks
            parser.MoveNextOrFail(); // guest_time
            parser.MoveNextOrFail(); // cguest_time

            result = results;
            return(true);
        }
Exemplo n.º 12
0
        internal static bool TryParseStatusFile(string statusFilePath, out ParsedStatus result, ReusableTextReader reusableReader)
        {
            if (!TryReadFile(statusFilePath, reusableReader, out string fileContents))
            {
                // Between the time that we get an ID and the time that we try to read the associated stat
                // file(s), the process could be gone.
                result = default(ParsedStatus);
                return(false);
            }

            ParsedStatus        results            = default(ParsedStatus);
            ReadOnlySpan <char> statusFileContents = fileContents.AsSpan();
            int unitSliceLength = -1;

#if DEBUG
            int nonUnitSliceLength = -1;
#endif
            while (!statusFileContents.IsEmpty)
            {
                int startIndex = statusFileContents.IndexOf(':');
                if (startIndex == -1)
                {
                    // Reached end of file
                    break;
                }

                ReadOnlySpan <char> title = statusFileContents.Slice(0, startIndex);
                statusFileContents = statusFileContents.Slice(startIndex + 1);
                int endIndex = statusFileContents.IndexOf('\n');
                if (endIndex == -1)
                {
                    endIndex        = statusFileContents.Length - 1;
                    unitSliceLength = statusFileContents.Length - 3;
#if DEBUG
                    nonUnitSliceLength = statusFileContents.Length;
#endif
                }
                else
                {
                    unitSliceLength = endIndex - 3;
#if DEBUG
                    nonUnitSliceLength = endIndex;
#endif
                }

                ReadOnlySpan <char> value = default;
                bool valueParsed          = true;
#if DEBUG
                if (title.SequenceEqual("Pid".AsSpan()))
                {
                    value       = statusFileContents.Slice(0, nonUnitSliceLength);
                    valueParsed = int.TryParse(value, out results.Pid);
                }
#endif
                if (title.SequenceEqual("VmHWM".AsSpan()))
                {
                    value       = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed = ulong.TryParse(value, out results.VmHWM);
                }
                else if (title.SequenceEqual("VmRSS".AsSpan()))
                {
                    value       = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed = ulong.TryParse(value, out results.VmRSS);
                }
                else if (title.SequenceEqual("VmData".AsSpan()))
                {
                    value           = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed     = ulong.TryParse(value, out ulong vmData);
                    results.VmData += vmData;
                }
                else if (title.SequenceEqual("VmSwap".AsSpan()))
                {
                    value       = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed = ulong.TryParse(value, out results.VmSwap);
                }
                else if (title.SequenceEqual("VmSize".AsSpan()))
                {
                    value       = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed = ulong.TryParse(value, out results.VmSize);
                }
                else if (title.SequenceEqual("VmPeak".AsSpan()))
                {
                    value       = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed = ulong.TryParse(value, out results.VmPeak);
                }
                else if (title.SequenceEqual("VmStk".AsSpan()))
                {
                    value           = statusFileContents.Slice(0, unitSliceLength);
                    valueParsed     = ulong.TryParse(value, out ulong vmStack);
                    results.VmData += vmStack;
                }

                Debug.Assert(valueParsed);
                statusFileContents = statusFileContents.Slice(endIndex + 1);
            }

            results.VmData *= 1024;
            results.VmPeak *= 1024;
            results.VmSize *= 1024;
            results.VmSwap *= 1024;
            results.VmRSS  *= 1024;
            results.VmHWM  *= 1024;
            result          = results;
            return(true);
        }