From e3564c7491cbcdc0f8b524d2e32d4b83636e7fd2 Mon Sep 17 00:00:00 2001 From: Staffan Gustafsson Date: Tue, 22 Nov 2016 23:27:18 +0100 Subject: [PATCH 1/5] Adding Parent extended property to System.Diagnostics.Process --- .../commands/management/Process.cs | 172 +----------------- .../engine/ProcessCodeMethods.cs | 109 +++++++++++ .../engine/Types_Ps1Xml.cs | 2 + .../utils/ClrFacade.cs | 159 +++++++++++++++- .../System.Management.Automation.csproj | 3 + 5 files changed, 273 insertions(+), 172 deletions(-) create mode 100644 src/System.Management.Automation/engine/ProcessCodeMethods.cs diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs index 1a8a49d3688..5ccf67c46cf 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs @@ -752,183 +752,13 @@ protected override void ProcessRecord() } else { -#if CORECLR - WriteObject(AddProperties(IncludeUserName.IsPresent, process, this)); -#else - WriteObject(IncludeUserName.IsPresent ? AddUserNameToProcess(process, this) : process); -#endif + WriteObject(ClrFacade.AddProcessProperties(IncludeUserName.IsPresent, process)); } }//for loop } // ProcessRecord #endregion Overrides - #region IncludeUserName - - /// - /// New PSTypeName added to the process object - /// - private const string TypeNameForProcessWithUserName = "System.Diagnostics.Process#IncludeUserName"; - - /// - /// Add the 'UserName' NoteProperty to the Process object - /// - /// - /// - /// - internal object AddUserNameToProcess(Process process, Cmdlet cmdlet) - { - // Return null if we failed to get the owner information - string userName = RetrieveProcessUserName(process, cmdlet); - - PSObject processAsPsobj = PSObject.AsPSObject(process); - PSNoteProperty noteProperty = new PSNoteProperty("UserName", userName); - - processAsPsobj.Properties.Add(noteProperty, true); - processAsPsobj.TypeNames.Insert(0, TypeNameForProcessWithUserName); - - return processAsPsobj; - } - -#if CORECLR - /// - /// Add the 'UserName' and 'HandleCount' NoteProperties to the Process object. - /// - /// - /// - /// - /// - internal object AddProperties(bool includeUserName, Process process, Cmdlet cmdlet) - { - PSObject processAsPsobj = PSObject.AsPSObject(process); - if (includeUserName) - { - // Return null if we failed to get the owner information - string userName = RetrieveProcessUserName(process, cmdlet); - PSNoteProperty noteProperty = new PSNoteProperty("UserName", userName); - processAsPsobj.Properties.Add(noteProperty, true); - processAsPsobj.TypeNames.Insert(0, TypeNameForProcessWithUserName); - } - - // In CoreCLR, the System.Diagnostics.Process.HandleCount property does not exist. - // I am adding a note property HandleCount and temporarily setting it to zero. - // This issue will be fix for RTM and it is tracked by 5024994: Get-process does not populate the Handles field. - PSMemberInfo hasHandleCount = processAsPsobj.Properties["HandleCount"]; - if (hasHandleCount == null) - { - PSNoteProperty noteProperty = new PSNoteProperty("HandleCount", 0); - processAsPsobj.Properties.Add(noteProperty, true); - processAsPsobj.TypeNames.Insert(0, "System.Diagnostics.Process#HandleCount"); - } - - return processAsPsobj; - } -#endif - - /// - /// Retrieve the UserName through PInvoke - /// - /// - /// - /// - private static string RetrieveProcessUserName(Process process, Cmdlet cmdlet) - { - string userName = null; -#if UNIX - userName = Platform.NonWindowsGetUserFromPid(process.Id); -#else - IntPtr tokenUserInfo = IntPtr.Zero; - IntPtr processTokenHandler = IntPtr.Zero; - - const uint TOKEN_QUERY = 0x0008; - - try - { - do - { - int error; - if (!Win32Native.OpenProcessToken(ClrFacade.GetSafeProcessHandle(process), TOKEN_QUERY, out processTokenHandler)) { break; } - - // Set the default length to be 256, so it will be sufficient for most cases - int tokenInfoLength = 256; - tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength); - if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength)) - { - error = Marshal.GetLastWin32Error(); - if (error == Win32Native.ERROR_INSUFFICIENT_BUFFER) - { - Marshal.FreeHGlobal(tokenUserInfo); - tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength); - - if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength)) { break; } - } - else - { - break; - } - } - - var tokenUser = ClrFacade.PtrToStructure(tokenUserInfo); - - // Set the default length to be 256, so it will be sufficient for most cases - int userNameLength = 256, domainNameLength = 256; - var userNameStr = new StringBuilder(userNameLength); - var domainNameStr = new StringBuilder(domainNameLength); - Win32Native.SID_NAME_USE accountType; - - if (!Win32Native.LookupAccountSid(null, tokenUser.User.Sid, userNameStr, ref userNameLength, domainNameStr, ref domainNameLength, out accountType)) - { - error = Marshal.GetLastWin32Error(); - if (error == Win32Native.ERROR_INSUFFICIENT_BUFFER) - { - userNameStr.EnsureCapacity(userNameLength); - domainNameStr.EnsureCapacity(domainNameLength); - - if (!Win32Native.LookupAccountSid(null, tokenUser.User.Sid, userNameStr, ref userNameLength, domainNameStr, ref domainNameLength, out accountType)) { break; } - } - else - { - break; - } - } - - userName = domainNameStr + "\\" + userNameStr; - } while (false); - } - catch (NotSupportedException) - { - // The Process not started yet, or it's a process from a remote machine - } - catch (InvalidOperationException) - { - // The Process has exited, Process.Handle will raise this exception - } - catch (Win32Exception) - { - // We might get an AccessDenied error - } - catch (Exception) - { - // I don't expect to get other exceptions, - } - finally - { - if (tokenUserInfo != IntPtr.Zero) - { - Marshal.FreeHGlobal(tokenUserInfo); - } - - if (processTokenHandler != IntPtr.Zero) - { - Win32Native.CloseHandle(processTokenHandler); - } - } - -#endif - return userName; - } - - #endregion IncludeUserName }//GetProcessCommand #endregion GetProcessCommand diff --git a/src/System.Management.Automation/engine/ProcessCodeMethods.cs b/src/System.Management.Automation/engine/ProcessCodeMethods.cs new file mode 100644 index 00000000000..a9eeee6f2ec --- /dev/null +++ b/src/System.Management.Automation/engine/ProcessCodeMethods.cs @@ -0,0 +1,109 @@ +using System; +using System.Diagnostics; +using System.Management.Automation; +using System.Runtime.InteropServices; + +namespace Microsoft.PowerShell { + /// + /// Helper functions for process info + /// + public static class ProcessCodeMethods + { + const int InvalidProcessId = -1; + + internal static Process GetParent(this Process process) + { + try + { + var pid = GetParentPid(process); + if (pid == InvalidProcessId) + { + return null; + } + var candidate = Process.GetProcessById(pid); + + // if the candidate was started later than process, the pid has been recycled + return candidate.StartTime > process.StartTime ? null : candidate; + } + catch (Exception) + { + return null; + } + } + + /// + /// CodeMethod for getting the parent process of a process + /// + /// + /// the parent process, or null if the parent is no longer running + public static PSObject GetParentProcess(PSObject obj) + { + var process = PSObject.Base(obj) as Process; + var parent = process?.GetParent(); + return parent != null ? ClrFacade.AddProcessProperties(false, parent) : null; + } + + /// + /// Returns the parent id of a process or -1 if it fails + /// + /// + /// the pid of the parent process +#if UNIX + internal static int GetParentPid(Process process) + { + // read /proc//stat + // 4th column will contain the ppid, 92 in the example below + // ex: 93 (bash) S 92 93 2 4294967295 ... + + var path = $"/proc/{process.Id}/stat"; + try + { + var stat = System.IO.File.ReadAllText(path); + var parts = stat.Split(new[] { ' ' }, 5); + if (parts.Length < 5) + { + return InvalidProcessId; + } + return Int32.Parse(parts[3]); + } + catch (Exception) + { + return InvalidProcessId; + } + } +#else + internal static int GetParentPid(Process process) + { + Diagnostics.Assert(process != null, "Ensure process is not null before calling"); + PROCESS_BASIC_INFORMATION pbi; + int size; +#if CORECLR + var res = NtQueryInformationProcess(process.SafeHandle.DangerousGetHandle(), 0, out pbi, Marshal.SizeOf(), out size); +#else + var res = NtQueryInformationProcess(process.Handle, 0, out pbi, Marshal.SizeOf(), out size); +#endif + return res != 0 ? InvalidProcessId : pbi.InheritedFromUniqueProcessId.ToInt32(); + } + + [StructLayout(LayoutKind.Sequential)] + struct PROCESS_BASIC_INFORMATION + { + public IntPtr ExitStatus; + public IntPtr PebBaseAddress; + public IntPtr AffinityMask; + public IntPtr BasePriority; + public IntPtr UniqueProcessId; + public IntPtr InheritedFromUniqueProcessId; + } + + [DllImport("ntdll.dll", SetLastError = true)] + static extern int NtQueryInformationProcess( + IntPtr processHandle, + int processInformationClass, + out PROCESS_BASIC_INFORMATION processInformation, + int processInformationLength, + out int returnLength); +#endif + + } +} \ No newline at end of file diff --git a/src/System.Management.Automation/engine/Types_Ps1Xml.cs b/src/System.Management.Automation/engine/Types_Ps1Xml.cs index 7c743250fb6..f90ee3f1652 100644 --- a/src/System.Management.Automation/engine/Types_Ps1Xml.cs +++ b/src/System.Management.Automation/engine/Types_Ps1Xml.cs @@ -272,6 +272,8 @@ public static IEnumerable Get() new AliasPropertyData("NPM", "NonpagedSystemMemorySize64")); td26.Members.Add("Path", new ScriptPropertyData(@"Path", GetScriptBlock(@"$this.Mainmodule.FileName"), null)); + td26.Members.Add("Parent", + new CodePropertyData("Parent", GetMethodInfo(typeof(Microsoft.PowerShell.ProcessCodeMethods), @"GetParentProcess"))); td26.Members.Add("Company", new ScriptPropertyData(@"Company", GetScriptBlock(@"$this.Mainmodule.FileVersionInfo.CompanyName"), null)); td26.Members.Add("CPU", diff --git a/src/System.Management.Automation/utils/ClrFacade.cs b/src/System.Management.Automation/utils/ClrFacade.cs index 2c7a8f713aa..5ab5111de89 100644 --- a/src/System.Management.Automation/utils/ClrFacade.cs +++ b/src/System.Management.Automation/utils/ClrFacade.cs @@ -26,9 +26,12 @@ using System.Management.Automation.Internal; using System.Text.RegularExpressions; #else -using Microsoft.PowerShell.Commands.Internal; /* used in the facade APIs related to 'SafeProcessHandle' */ using System.Runtime.Serialization; /* used in facade API 'GetUninitializedObject' */ #endif +#if !UNIX +using System.ComponentModel; /* used in the facade API RetrieveProcessUserName */ +using Microsoft.PowerShell.Commands.Internal; /* used in the facade APIs related to 'SafeProcessHandle' and 'RetreiveUserName' */ +#endif namespace System.Management.Automation { @@ -114,6 +117,160 @@ internal static IntPtr GetRawProcessHandle(Process process) #endif } +#region Facade for AddProcessProperties + + /// + /// Ensures the 'UserName' and 'HandleCount' Properties exist the Process object. + /// + /// + /// + /// + internal static PSObject AddProcessProperties(bool includeUserName, Process process) + { + PSObject processAsPsobj = includeUserName ? AddUserNameToProcess(process) : PSObject.AsPSObject(process); +#if CORECLR + // In CoreCLR, the System.Diagnostics.Process.HandleCount property does not exist. + // I am adding a note property HandleCount and temporarily setting it to zero. + // This issue will be fix for RTM and it is tracked by 5024994: Get-process does not populate the Handles field. + PSMemberInfo hasHandleCount = processAsPsobj.Properties["HandleCount"]; + if (hasHandleCount == null) + { + PSNoteProperty noteProperty = new PSNoteProperty("HandleCount", 0); + processAsPsobj.Properties.Add(noteProperty, true); + processAsPsobj.TypeNames.Insert(0, "System.Diagnostics.Process#HandleCount"); + } +#endif + return processAsPsobj; + } + /// + /// New PSTypeName added to the process object + /// + private const string TypeNameForProcessWithUserName = "System.Diagnostics.Process#IncludeUserName"; + + /// + /// Add the 'UserName' NoteProperty to the Process object + /// + /// + /// + private static PSObject AddUserNameToProcess(Process process) + { + // Return null if we failed to get the owner information + string userName = ClrFacade.RetrieveProcessUserName(process); + + PSObject processAsPsobj = PSObject.AsPSObject(process); + PSNoteProperty noteProperty = new PSNoteProperty("UserName", userName); + + processAsPsobj.Properties.Add(noteProperty, true); + processAsPsobj.TypeNames.Insert(0, TypeNameForProcessWithUserName); + + return processAsPsobj; + } + + + /// + /// Retrieve the UserName through PInvoke + /// + /// + /// + private static string RetrieveProcessUserName(Process process) + { + string userName = null; +#if UNIX + userName = Platform.NonWindowsGetUserFromPid(process.Id); +#else + IntPtr tokenUserInfo = IntPtr.Zero; + IntPtr processTokenHandler = IntPtr.Zero; + + const uint TOKEN_QUERY = 0x0008; + + try + { + do + { + int error; + if (!Win32Native.OpenProcessToken(ClrFacade.GetSafeProcessHandle(process), TOKEN_QUERY, out processTokenHandler)) { break; } + + // Set the default length to be 256, so it will be sufficient for most cases + int tokenInfoLength = 256; + tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength); + if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength)) + { + error = Marshal.GetLastWin32Error(); + if (error == Win32Native.ERROR_INSUFFICIENT_BUFFER) + { + Marshal.FreeHGlobal(tokenUserInfo); + tokenUserInfo = Marshal.AllocHGlobal(tokenInfoLength); + + if (!Win32Native.GetTokenInformation(processTokenHandler, Win32Native.TOKEN_INFORMATION_CLASS.TokenUser, tokenUserInfo, tokenInfoLength, out tokenInfoLength)) { break; } + } + else + { + break; + } + } + + var tokenUser = ClrFacade.PtrToStructure(tokenUserInfo); + + // Set the default length to be 256, so it will be sufficient for most cases + int userNameLength = 256, domainNameLength = 256; + var userNameStr = new StringBuilder(userNameLength); + var domainNameStr = new StringBuilder(domainNameLength); + Win32Native.SID_NAME_USE accountType; + + if (!Win32Native.LookupAccountSid(null, tokenUser.User.Sid, userNameStr, ref userNameLength, domainNameStr, ref domainNameLength, out accountType)) + { + error = Marshal.GetLastWin32Error(); + if (error == Win32Native.ERROR_INSUFFICIENT_BUFFER) + { + userNameStr.EnsureCapacity(userNameLength); + domainNameStr.EnsureCapacity(domainNameLength); + + if (!Win32Native.LookupAccountSid(null, tokenUser.User.Sid, userNameStr, ref userNameLength, domainNameStr, ref domainNameLength, out accountType)) { break; } + } + else + { + break; + } + } + + userName = domainNameStr + "\\" + userNameStr; + } while (false); + } + catch (NotSupportedException) + { + // The Process not started yet, or it's a process from a remote machine + } + catch (InvalidOperationException) + { + // The Process has exited, Process.Handle will raise this exception + } + catch (Win32Exception) + { + // We might get an AccessDenied error + } + catch (Exception) + { + // I don't expect to get other exceptions, + } + finally + { + if (tokenUserInfo != IntPtr.Zero) + { + Marshal.FreeHGlobal(tokenUserInfo); + } + + if (processTokenHandler != IntPtr.Zero) + { + Win32Native.CloseHandle(processTokenHandler); + } + } + +#endif + return userName; + } + +#endregion + #if CORECLR /// /// Facade for ProcessStartInfo.Environment diff --git a/src/vs-csproj/System.Management.Automation.csproj b/src/vs-csproj/System.Management.Automation.csproj index e320fdb90c7..3951e3faac8 100644 --- a/src/vs-csproj/System.Management.Automation.csproj +++ b/src/vs-csproj/System.Management.Automation.csproj @@ -1081,6 +1081,9 @@ engine\PositionalCommandParameter.cs + + engine\ProcessCodeMethods.cs + engine\ProgressRecord.cs From fea2f00eafa69ef91a8fcb84c8da7ed488324684 Mon Sep 17 00:00:00 2001 From: powercode Date: Mon, 27 Feb 2017 17:27:14 +0100 Subject: [PATCH 2/5] Adding test for process parent. --- .../Get-Process.Tests.ps1 | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 index 4a0c34d3f7a..185c27abc0b 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/Get-Process.Tests.ps1 @@ -22,12 +22,10 @@ Describe "Get-Process Formatting" -Tags "Feature" { It "Should not have Handle in table format header" { $types = "System.Diagnostics.Process","System.Diagnostics.Process#IncludeUserName" - foreach ($type in $types) - { + foreach ($type in $types) { $formatData = Get-FormatData -TypeName $type -PowerShellVersion $PSVersionTable.PSVersion $tableControls = $formatData.FormatViewDefinition | Where-Object {$_.Control -is "System.Management.Automation.TableControl"} - foreach ($tableControl in $tableControls) - { + foreach ($tableControl in $tableControls) { $tableControl.Control.Headers.Label -match "Handle*" | Should BeNullOrEmpty # verify that rows without headers isn't the handlecount (as PowerShell will create a header that matches the property name) $tableControl.Control.Rows.Columns.DisplayEntry.Value -eq "HandleCount" | Should BeNullOrEmpty @@ -35,3 +33,16 @@ Describe "Get-Process Formatting" -Tags "Feature" { } } } + +Describe "Process Parent property" -Tags "CI" { + It "Has Parent process property" { + $powershellexe = (get-process -id $PID).mainmodule.filename + & $powershellexe -noprofile -command '(Get-Process -Id $pid).Parent' | Should Not be $null + } + + It "Has valid parent process ID property" { + $powershellexe = (get-process -id $PID).mainmodule.filename + & $powershellexe -noprofile -command '(Get-Process -Id $pid).Parent.Id' | Should Be $pid + } +} + From 17441c734e525d0683fe884efb07ee3cf43096c3 Mon Sep 17 00:00:00 2001 From: powercode Date: Wed, 1 Mar 2017 05:00:16 +0100 Subject: [PATCH 3/5] Changing implementation for unix to use sysctl call. --- .../CoreCLR/CorePsPlatform.cs | 34 ++++++++++++++++ .../engine/ProcessCodeMethods.cs | 22 +---------- src/libpsl-native/src/CMakeLists.txt | 1 + src/libpsl-native/src/getppid.cpp | 39 +++++++++++++++++++ src/libpsl-native/src/getppid.h | 10 +++++ 5 files changed, 86 insertions(+), 20 deletions(-) create mode 100644 src/libpsl-native/src/getppid.cpp create mode 100644 src/libpsl-native/src/getppid.h diff --git a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs index 62f84e8545f..bfa97145444 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs @@ -451,6 +451,13 @@ internal static uint NonWindowsGetThreadId() return Unix.NativeMethods.GetCurrentThreadId(); } + internal static int NonWindowsGetProcessParentPid(int pid) + { + return IsOSX ? Unix.NativeMethods.GetPPid(pid) : Unix.GetProcFSParentPid(pid); + } + + + // Unix specific implementations of required functionality // // Please note that `Win32Exception(Marshal.GetLastWin32Error())` @@ -525,6 +532,30 @@ public static bool IsHardLink(FileSystemInfo fs) } } + public static int GetProcFSParentPid(int pid) + { + const int invalidPid = -1; + // read /proc//stat + // 4th column will contain the ppid, 92 in the example below + // ex: 93 (bash) S 92 93 2 4294967295 ... + + var path = $"/proc/{pid}/stat"; + try + { + var stat = System.IO.File.ReadAllText(path); + var parts = stat.Split(new[] { ' ' }, 5); + if (parts.Length < 5) + { + return invalidPid; + } + return Int32.Parse(parts[3]); + } + catch (Exception) + { + return invalidPid; + } + } + internal static class NativeMethods { private const string psLib = "libpsl-native"; @@ -540,6 +571,9 @@ internal static class NativeMethods [return: MarshalAs(UnmanagedType.LPStr)] internal static extern string GetUserName(); + [DllImport(psLib)] + internal static extern int GetPPid(int pid); + [DllImport(psLib, CharSet = CharSet.Ansi, SetLastError = true)] internal static extern int GetLinkCount([MarshalAs(UnmanagedType.LPStr)]string filePath, out int linkCount); diff --git a/src/System.Management.Automation/engine/ProcessCodeMethods.cs b/src/System.Management.Automation/engine/ProcessCodeMethods.cs index a9eeee6f2ec..2ad832f8465 100644 --- a/src/System.Management.Automation/engine/ProcessCodeMethods.cs +++ b/src/System.Management.Automation/engine/ProcessCodeMethods.cs @@ -49,27 +49,9 @@ public static PSObject GetParentProcess(PSObject obj) /// /// the pid of the parent process #if UNIX - internal static int GetParentPid(Process process) + internal static int GetParentPid(Process process) { - // read /proc//stat - // 4th column will contain the ppid, 92 in the example below - // ex: 93 (bash) S 92 93 2 4294967295 ... - - var path = $"/proc/{process.Id}/stat"; - try - { - var stat = System.IO.File.ReadAllText(path); - var parts = stat.Split(new[] { ' ' }, 5); - if (parts.Length < 5) - { - return InvalidProcessId; - } - return Int32.Parse(parts[3]); - } - catch (Exception) - { - return InvalidProcessId; - } + return Platform.NonWindowsGetProcessParentPid(process.Id); } #else internal static int GetParentPid(Process process) diff --git a/src/libpsl-native/src/CMakeLists.txt b/src/libpsl-native/src/CMakeLists.txt index 9a3be5701d5..6cb86d0169d 100644 --- a/src/libpsl-native/src/CMakeLists.txt +++ b/src/libpsl-native/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(psl-native SHARED getstat.cpp getpwuid.cpp + getppid.cpp getuserfrompid.cpp getfileowner.cpp getcurrentthreadid.cpp diff --git a/src/libpsl-native/src/getppid.cpp b/src/libpsl-native/src/getppid.cpp new file mode 100644 index 00000000000..a5297277eb7 --- /dev/null +++ b/src/libpsl-native/src/getppid.cpp @@ -0,0 +1,39 @@ +#include "getppid.h" + +#include +#include +#include + +//! @brief GetPPid returns the parent process id for a process +//! +//! GetPPid +//! +//! @param[in] pid +//! @parblock +//! The process id to query for it's parent. +//! @endparblock +//! +//! @retval the parent process id, or UINT_MAX if unsuccessful +//! +pid_t GetPPid(pid_t pid) +{ + +#if defined(__APPLE__) && defined(__MACH__) + + const pid_t PIDUnknown = UINT_MAX; + struct kinfo_proc info; + size_t length = sizeof(struct kinfo_proc); + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + if (sysctl(mib, 4, &info, &length, NULL, 0) < 0) + return PIDUnknown; + if (length == 0) + return PIDUnknown; + + return info.kp_eproc.e_ppid; + +#else + + return UINT_MAX; + +#endif +} \ No newline at end of file diff --git a/src/libpsl-native/src/getppid.h b/src/libpsl-native/src/getppid.h new file mode 100644 index 00000000000..46c9cfc9cd2 --- /dev/null +++ b/src/libpsl-native/src/getppid.h @@ -0,0 +1,10 @@ +#pragma once + +#include "pal.h" +#include + +PAL_BEGIN_EXTERNC + +pid_t GetPPid(pid_t pid); + +PAL_END_EXTERNC From e51230f33b74ac195b8dc5f1488f93d2f9f45e73 Mon Sep 17 00:00:00 2001 From: Jason Shirk Date: Thu, 2 Mar 2017 08:53:42 -0800 Subject: [PATCH 4/5] replace tabs with spaces --- src/System.Management.Automation/engine/ProcessCodeMethods.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/ProcessCodeMethods.cs b/src/System.Management.Automation/engine/ProcessCodeMethods.cs index 2ad832f8465..7cc8fc4cf2e 100644 --- a/src/System.Management.Automation/engine/ProcessCodeMethods.cs +++ b/src/System.Management.Automation/engine/ProcessCodeMethods.cs @@ -49,7 +49,7 @@ public static PSObject GetParentProcess(PSObject obj) /// /// the pid of the parent process #if UNIX - internal static int GetParentPid(Process process) + internal static int GetParentPid(Process process) { return Platform.NonWindowsGetProcessParentPid(process.Id); } @@ -88,4 +88,4 @@ static extern int NtQueryInformationProcess( #endif } -} \ No newline at end of file +} From ee1cecb4bbf08854fdd1a54dad8d0895ec69140f Mon Sep 17 00:00:00 2001 From: Jason Shirk Date: Thu, 2 Mar 2017 09:07:55 -0800 Subject: [PATCH 5/5] add newline at eof --- src/libpsl-native/src/getppid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libpsl-native/src/getppid.cpp b/src/libpsl-native/src/getppid.cpp index a5297277eb7..c562f4c7e24 100644 --- a/src/libpsl-native/src/getppid.cpp +++ b/src/libpsl-native/src/getppid.cpp @@ -36,4 +36,4 @@ pid_t GetPPid(pid_t pid) return UINT_MAX; #endif -} \ No newline at end of file +}