Add and use Environment.ProcessId (#38908)
authorStephen Toub <stoub@microsoft.com>
Thu, 9 Jul 2020 22:09:05 +0000 (18:09 -0400)
committerGitHub <noreply@github.com>
Thu, 9 Jul 2020 22:09:05 +0000 (18:09 -0400)
* Add and use Environment.ProcessId

* Split newly added tests

32 files changed:
src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.Unix.cs [deleted file]
src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.Windows.cs [deleted file]
src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.cs [deleted file]
src/libraries/System.Console/tests/CancelKeyPress.Unix.cs
src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.BSD.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.FreeBSD.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.OSX.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Windows.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs
src/libraries/System.Diagnostics.Process/tests/Interop.Unix.cs
src/libraries/System.Diagnostics.Process/tests/Interop.cs
src/libraries/System.Diagnostics.Process/tests/ProcessTests.cs
src/libraries/System.Diagnostics.TextWriterTraceListener/src/System.Diagnostics.TextWriterTraceListener.csproj
src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs
src/libraries/System.Diagnostics.TextWriterTraceListener/tests/XmlWriterTraceListenerTests.cs
src/libraries/System.Diagnostics.TraceSource/src/System.Diagnostics.TraceSource.csproj
src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/TraceEventCache.cs
src/libraries/System.Diagnostics.TraceSource/tests/TraceEventCacheClassTests.cs
src/libraries/System.Net.Sockets/tests/FunctionalTests/CreateSocketTests.cs
src/libraries/System.Net.Sockets/tests/FunctionalTests/SocketDuplicationTests.cs
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Environment.Unix.cs
src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Environment.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.Unix.cs [deleted file]
src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.Windows.cs [deleted file]
src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.cs
src/libraries/System.Runtime.Extensions/tests/System/EnvironmentTests.cs
src/libraries/System.Runtime/ref/System.Runtime.cs

diff --git a/src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.Unix.cs b/src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.Unix.cs
deleted file mode 100644 (file)
index 64df4e7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Diagnostics
-{
-    internal static partial class TraceListenerHelpers
-    {
-        internal static int GetProcessId()
-        {
-            // Whereas the Win32 implementation caches the GetProcessId result, the Unix
-            // implementation doesn't so as to avoid problems with fork'd child processes
-            // ending up returning the same id as the parent.
-            return Interop.Sys.GetPid();
-        }
-
-        internal static string GetProcessName()
-        {
-            if (s_processName == null)
-            {
-                using (var process = Process.GetCurrentProcess())
-                {
-                    s_processName = process.ProcessName;
-                }
-            }
-
-            return s_processName;
-        }
-    }
-}
diff --git a/src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.Windows.cs b/src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.Windows.cs
deleted file mode 100644 (file)
index 682f714..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Diagnostics
-{
-    internal static partial class TraceListenerHelpers
-    {
-        private static volatile bool s_hasProcessId;
-        private static volatile int s_processId;
-
-        internal static int GetProcessId()
-        {
-            if (!s_hasProcessId)
-            {
-                s_processId = (int)Interop.Kernel32.GetCurrentProcessId();
-                s_hasProcessId = true;
-            }
-
-            return s_processId;
-        }
-
-        internal static string GetProcessName()
-        {
-
-            if (s_processName == null)
-            {
-                using (var process = Process.GetCurrentProcess())
-                {
-                    s_processName = process.ProcessName;
-                }
-            }
-
-            return s_processName;
-        }
-    }
-}
diff --git a/src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.cs b/src/libraries/Common/src/System/Diagnostics/TraceListenerHelpers.cs
deleted file mode 100644 (file)
index 2d9c689..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-#nullable enable
-namespace System.Diagnostics
-{
-    internal static partial class TraceListenerHelpers
-    {
-        private static volatile string? s_processName;
-
-        internal static int GetThreadId()
-        {
-            return Environment.CurrentManagedThreadId;
-        }
-    }
-}
index 978ba7c..04c31b5 100644 (file)
@@ -61,7 +61,7 @@ public partial class CancelKeyPressTests
             };
 
             // Generate CancelKeyPress
-            Assert.Equal(0, kill(Process.GetCurrentProcess().Id, SIGINT));
+            Assert.Equal(0, kill(Environment.ProcessId, SIGINT));
             // Wait till we block CancelKeyPress
             Assert.True(tcs.Task.Wait(WaitFailTestTimeoutSeconds * 1000));
 
@@ -101,7 +101,7 @@ public partial class CancelKeyPressTests
             try
             {
                 int signalInner = int.Parse(signalStr);
-                Assert.Equal(0, kill(Process.GetCurrentProcess().Id, signalInner));
+                Assert.Equal(0, kill(Environment.ProcessId, signalInner));
                 Assert.True(tcs.Task.Wait(WaitFailTestTimeoutSeconds * 1000));
                 Assert.Equal(
                     signalInner == SIGINT ? ConsoleSpecialKey.ControlC : ConsoleSpecialKey.ControlBreak,
index b42fd17..c7165ca 100644 (file)
              Link="Common\Interop\Windows\Advapi32\Interop.AdjustTokenPrivileges.cs" />
     <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetComputerName.cs"
              Link="Common\Interop\Windows\Kernel32\Interop.GetComputerName.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs"
-             Link="Common\Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs" />
     <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetConsoleCP.cs"
              Link="Common\Interop\Windows\Kernel32\Interop.GetConsoleCP.cs" />
     <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetConsoleOutputCP.cs"
              Link="Common\Interop\Unix\Interop.GetGroupList.cs" />
     <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetLine.cs"
              Link="Common\Interop\Unix\Interop.GetLine.cs" />
-    <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetPid.cs"
-             Link="Common\Interop\Unix\Interop.GetPid.cs" />
     <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetPwUid.cs"
              Link="Common\Interop\Unix\Interop.GetPwUid.cs" />
     <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetSetPriority.cs"
index 69533c8..ec2e319 100644 (file)
@@ -59,7 +59,7 @@ namespace System.Diagnostics
         private void GetWorkingSetLimits(out IntPtr minWorkingSet, out IntPtr maxWorkingSet)
         {
             // We can only do this for the current process on OS X
-            if (_processId != Interop.Sys.GetPid())
+            if (_processId != Environment.ProcessId)
                 throw new PlatformNotSupportedException(SR.OsxExternalProcessWorkingSetNotSupported);
 
             // Minimum working set (or resident set, as it is called on *nix) doesn't exist so set to 0
@@ -88,7 +88,7 @@ namespace System.Diagnostics
         private void SetWorkingSetLimitsCore(IntPtr? newMin, IntPtr? newMax, out IntPtr resultingMin, out IntPtr resultingMax)
         {
             // We can only do this for the current process on OS X
-            if (_processId != Interop.Sys.GetPid())
+            if (_processId != Environment.ProcessId)
                 throw new PlatformNotSupportedException(SR.OsxExternalProcessWorkingSetNotSupported);
 
             // There isn't a way to set the minimum working set, so throw an exception here
index c240794..398d267 100644 (file)
@@ -104,7 +104,7 @@ namespace System.Diagnostics
         /// <summary>Gets the path to the current executable, or null if it could not be retrieved.</summary>
         private static string? GetExePath()
         {
-            return Interop.Process.GetProcPath(Interop.Sys.GetPid());
+            return Interop.Process.GetProcPath(Environment.ProcessId);
         }
 
         // ----------------------------------
index e222450..cab74e4 100644 (file)
@@ -94,7 +94,7 @@ namespace System.Diagnostics
         /// <summary>Gets the path to the current executable, or null if it could not be retrieved.</summary>
         private static string GetExePath()
         {
-            return Interop.libproc.proc_pidpath(Interop.Sys.GetPid());
+            return Interop.libproc.proc_pidpath(Environment.ProcessId);
         }
 
         // ----------------------------------
@@ -103,7 +103,7 @@ namespace System.Diagnostics
 
         private Interop.libproc.rusage_info_v3 GetCurrentProcessRUsage()
         {
-            return Interop.libproc.proc_pid_rusage(Interop.Sys.GetPid());
+            return Interop.libproc.proc_pid_rusage(Environment.ProcessId);
         }
     }
 }
index b13a42c..131912f 100644 (file)
@@ -305,12 +305,6 @@ namespace System.Diagnostics
             }
         }
 
-        /// <summary>Gets the ID of the current process.</summary>
-        private static int GetCurrentProcessId()
-        {
-            return Interop.Sys.GetPid();
-        }
-
         /// <summary>Checks whether the argument is a direct child of this process.</summary>
         private bool IsParentOf(Process possibleChildProcess) =>
             Id == possibleChildProcess.ParentProcessId;
index 520ab52..34e1762 100644 (file)
@@ -367,12 +367,6 @@ namespace System.Diagnostics
             }
         }
 
-        /// <summary>Gets the ID of the current process.</summary>
-        private static int GetCurrentProcessId()
-        {
-            return unchecked((int)Interop.Kernel32.GetCurrentProcessId());
-        }
-
         /// <summary>
         /// Gets a short-term handle to the process, with the given access.  If a handle exists,
         /// then it is reused.  If the process has exited, it throws an exception.
index 8f802cb..e47cac9 100644 (file)
@@ -1069,7 +1069,7 @@ namespace System.Diagnostics
         /// </devdoc>
         public static Process GetCurrentProcess()
         {
-            return new Process(".", false, GetCurrentProcessId(), null);
+            return new Process(".", false, Environment.ProcessId, null);
         }
 
         /// <devdoc>
index 49d3194..38512de 100644 (file)
@@ -96,7 +96,7 @@ namespace System.Diagnostics
                     SafeProcessHandle hCurProcess = SafeProcessHandle.InvalidHandle;
                     try
                     {
-                        hCurProcess = ProcessManager.OpenProcess((int)Interop.Kernel32.GetCurrentProcessId(), Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION, true);
+                        hCurProcess = ProcessManager.OpenProcess(Environment.ProcessId, Interop.Advapi32.ProcessOptions.PROCESS_QUERY_INFORMATION, true);
 
                         if (!Interop.Kernel32.IsWow64Process(hCurProcess, out bool sourceProcessIsWow64))
                         {
index 71883ef..5cc19a0 100644 (file)
@@ -11,9 +11,6 @@ namespace System.Diagnostics.Tests
     internal partial class Interop
     {
         [DllImport("libc")]
-        internal static extern int getpid();
-
-        [DllImport("libc")]
         internal static extern int getsid(int pid);
     }
 }
index d10e65e..e738872 100644 (file)
@@ -55,9 +55,6 @@ namespace System.Diagnostics.Tests
         public static extern bool GetProcessWorkingSetSizeEx(SafeProcessHandle hProcess, out IntPtr lpMinimumWorkingSetSize, out IntPtr lpMaximumWorkingSetSize, out uint flags);
 
         [DllImport("kernel32.dll")]
-        internal static extern int GetCurrentProcessId();
-
-        [DllImport("kernel32.dll")]
         internal static extern bool ProcessIdToSessionId(uint dwProcessId, out uint pSessionId);
 
         [DllImport("kernel32.dll")]
index ef50d90..ca9a3f6 100644 (file)
@@ -408,11 +408,20 @@ namespace System.Diagnostics.Tests
             Assert.Throws<InvalidOperationException>(() => process.StartTime);
         }
 
+        [Fact]
+        public void GetCurrentProcess_Id_EqualsCurrentProcessId()
+        {
+            using Process current = Process.GetCurrentProcess();
+            Assert.Equal(Environment.ProcessId, current.Id);
+        }
+
         [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
         public void TestId()
         {
             CreateDefaultProcess();
 
+            Assert.NotEqual(Environment.ProcessId, _process.Id);
+
             if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
             {
                 Assert.Equal(_process.Id, Interop.GetProcessId(_process.SafeHandle));
@@ -1050,12 +1059,7 @@ namespace System.Diagnostics.Tests
             Process current = Process.GetCurrentProcess();
             Assert.NotNull(current);
 
-            int currentProcessId =
-#if TargetsWindows
-                Interop.GetCurrentProcessId();
-#else
-                Interop.getpid();
-#endif
+            int currentProcessId = Environment.ProcessId;
 
             Assert.Equal(currentProcessId, current.Id);
         }
index 41a5392..ee094ea 100644 (file)
     <Compile Include="System\Diagnostics\DelimitedListTraceListener.cs" />
     <Compile Include="System\Diagnostics\TextWriterTraceListener.cs" />
     <Compile Include="System\Diagnostics\XmlWriterTraceListener.cs" />
-    <Compile Include="$(CommonPath)System\Diagnostics\TraceListenerHelpers.cs"
-             Link="Common\System\Diagnostics\TraceListenerHelpers.cs" />
-  </ItemGroup>
-  <ItemGroup Condition="'$(TargetsWindows)' == 'true'">
-    <Compile Include="$(CommonPath)System\Diagnostics\TraceListenerHelpers.Windows.cs"
-             Link="Common\System\Diagnostics\TraceListenerHelpers.Windows.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
-             Link="Common\Interop\Windows\Interop.Libraries.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs"
-             Link="Common\Interop\Windows\Interop.GetCurrentProcessId.cs" />
-  </ItemGroup>
-  <ItemGroup Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'">
-    <Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
-             Link="Common\Interop\Unix\Interop.Libraries.cs" />
-    <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetPid.cs"
-             Link="Common\Interop\Unix\Interop.GetPid.cs" />
-    <Compile Include="$(CommonPath)System\Diagnostics\TraceListenerHelpers.Unix.cs"
-             Link="Common\System\Diagnostics\TraceListenerHelpers.Unix.cs" />
   </ItemGroup>
   <ItemGroup>
     <Reference Include="System.ComponentModel.Primitives" />
index 26b6839..cf38c8d 100644 (file)
@@ -15,6 +15,7 @@ namespace System.Diagnostics
     {
         private const string FixedHeader = "<E2ETraceEvent xmlns=\"http://schemas.microsoft.com/2004/06/E2ETraceEvent\"><System xmlns=\"http://schemas.microsoft.com/2004/06/windows/eventlog/system\">";
 
+        private static volatile string? s_processName;
         private readonly string _machineName = Environment.MachineName;
         private StringBuilder? _strBldr;
         private XmlTextWriter? _xmlBlobWriter;
@@ -254,14 +255,21 @@ namespace System.Diagnostics
         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
         private void WriteEndHeader()
         {
+            string? processName = s_processName;
+            if (processName is null)
+            {
+                using Process process = Process.GetCurrentProcess();
+                s_processName = processName = process.ProcessName;
+            }
+
             InternalWrite("\" />");
 
             InternalWrite("<Execution ProcessName=\"");
-            InternalWrite(TraceListenerHelpers.GetProcessName());
+            InternalWrite(processName);
             InternalWrite("\" ProcessID=\"");
-            InternalWrite(((uint)TraceListenerHelpers.GetProcessId()).ToString(CultureInfo.InvariantCulture));
+            InternalWrite(((uint)Environment.ProcessId).ToString(CultureInfo.InvariantCulture));
             InternalWrite("\" ThreadID=\"");
-            WriteEscaped(TraceListenerHelpers.GetThreadId().ToString(CultureInfo.InvariantCulture));
+            WriteEscaped(Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture));
             InternalWrite("\" />");
 
             InternalWrite("<Channel/>");
index e55b6c9..efcfb6f 100644 (file)
@@ -102,12 +102,9 @@ namespace System.Diagnostics.TextWriterTraceListenerTests
         {
             // Ensure we use an arbitrary ID that doesn't match the process ID or thread ID.
             int traceTransferId = 1;
-            using (Process p = Process.GetCurrentProcess())
+            while (traceTransferId == Environment.ProcessId || traceTransferId == Environment.CurrentManagedThreadId)
             {
-                while (traceTransferId == p.Id || traceTransferId == Environment.CurrentManagedThreadId)
-                {
-                    traceTransferId++;
-                }
+                traceTransferId++;
             }
 
             string file = GetTestFilePath();
index c556e70..b13f7ff 100644 (file)
     <Compile Include="System\Diagnostics\TraceSwitch.cs" />
     <Compile Include="System\Diagnostics\SwitchAttribute.cs" />
     <Compile Include="System\Diagnostics\SwitchLevelAttribute.cs" />
-    <Compile Include="$(CommonPath)System\Diagnostics\TraceListenerHelpers.cs"
-             Link="Common\System\Diagnostics\TraceListenerHelpers.cs" />
-  </ItemGroup>
-  <ItemGroup Condition=" '$(TargetsWindows)' == 'true'">
-    <Compile Include="$(CommonPath)System\Diagnostics\TraceListenerHelpers.Windows.cs"
-             Link="Common\System\Diagnostics\TraceListenerHelpers.Windows.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
-             Link="Common\Interop\Windows\Interop.Libraries.cs" />
-    <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.GetCurrentProcessId.cs"
-             Link="Common\Interop\Windows\Interop.GetCurrentProcessId.cs" />
-  </ItemGroup>
-  <ItemGroup Condition=" '$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true'">
-    <Compile Include="$(CommonPath)Interop\Unix\Interop.Libraries.cs"
-             Link="Common\Interop\Unix\Interop.Libraries.cs" />
-    <Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.GetPid.cs"
-             Link="Common\Interop\Unix\Interop.GetPid.cs" />
-    <Compile Include="$(CommonPath)System\Diagnostics\TraceListenerHelpers.Unix.cs"
-             Link="Common\System\Diagnostics\TraceListenerHelpers.Unix.cs" />
   </ItemGroup>
   <ItemGroup>
     <ProjectReference Include="..\..\System.Collections\src\System.Collections.csproj" />
     <ProjectReference Include="..\..\System.Collections.NonGeneric\src\System.Collections.NonGeneric.csproj" />
     <ProjectReference Include="..\..\System.Collections.Specialized\src\System.Collections.Specialized.csproj " />
     <ProjectReference Include="..\..\System.ComponentModel.Primitives\src\System.ComponentModel.Primitives.csproj " />
-    <ProjectReference Include="..\..\System.Diagnostics.Process\src\System.Diagnostics.Process.csproj " />
     <ProjectReference Include="..\..\System.IO.FileSystem\src\System.IO.FileSystem.csproj " />
     <ProjectReference Include="..\..\System.Runtime\src\System.Runtime.csproj" />
     <ProjectReference Include="..\..\System.Runtime.Extensions\src\System.Runtime.Extensions.csproj" />
-    <ProjectReference Include="..\..\System.Runtime.InteropServices\src\System.Runtime.InteropServices.csproj" />
     <ProjectReference Include="..\..\System.Threading\src\System.Threading.csproj" />
   </ItemGroup>
   <ItemGroup>
index d377f74..cdc431d 100644 (file)
@@ -29,7 +29,7 @@ namespace System.Diagnostics
         {
             get
             {
-                return TraceListenerHelpers.GetProcessId();
+                return Environment.ProcessId;
             }
         }
 
@@ -37,7 +37,7 @@ namespace System.Diagnostics
         {
             get
             {
-                return TraceListenerHelpers.GetThreadId().ToString(CultureInfo.InvariantCulture);
+                return Environment.CurrentManagedThreadId.ToString(CultureInfo.InvariantCulture);
             }
         }
 
index 2874985..6933d03 100644 (file)
@@ -24,8 +24,8 @@ namespace System.Diagnostics.TraceSourceTests
         public void ProcessIdTest()
         {
             var cache = new TraceEventCache();
-            var id = cache.ProcessId;
-            var expected = System.Diagnostics.Process.GetCurrentProcess().Id;
+            int id = cache.ProcessId;
+            int expected = Environment.ProcessId;
             Assert.Equal((int)expected, id);
         }
 
index d490777..cf21032 100644 (file)
@@ -570,10 +570,10 @@ namespace System.Net.Sockets.Tests
             {
                 Assert.Equal(AddressFamily.Unknown, netlink.AddressFamily);
 
-                netlink.Bind(new NlEndPoint(Process.GetCurrentProcess().Id));
+                netlink.Bind(new NlEndPoint(Environment.ProcessId));
 
                 nl_request req = default;
-                req.nlh.nlmsg_pid = (uint)Process.GetCurrentProcess().Id;
+                req.nlh.nlmsg_pid = (uint)Environment.ProcessId;
                 req.nlh.nlmsg_type = RTM_GETROUTE;  /* We wish to get routes */
                 req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
                 req.nlh.nlmsg_len = sizeof(nl_request);
index 17cf3bb..2acd34c 100644 (file)
@@ -27,14 +27,6 @@ namespace System.Net.Sockets.Tests
         private static string GetMessageString(ArraySegment<byte> data, int count) =>
             Encoding.ASCII.GetString(data.AsSpan().Slice(0, count));
 
-        private static readonly Lazy<int> s_currentProcessId = new Lazy<int>(() =>
-        {
-            using var process = Process.GetCurrentProcess();
-            return process.Id;
-        }, LazyThreadSafetyMode.PublicationOnly);
-
-        private static int CurrentProcessId => s_currentProcessId.Value;
-
         [Fact]
         public void UseOnlyOverlappedIO_AlwaysFalse()
         {
@@ -62,7 +54,7 @@ namespace System.Net.Sockets.Tests
             Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
             socket.Dispose();
 
-            Assert.Throws<ObjectDisposedException>(() => socket.DuplicateAndClose(CurrentProcessId));
+            Assert.Throws<ObjectDisposedException>(() => socket.DuplicateAndClose(Environment.ProcessId));
         }
 
         [PlatformSpecific(TestPlatforms.Windows)]
@@ -77,7 +69,7 @@ namespace System.Net.Sockets.Tests
             };
             Assert.Equal(blocking, original.Blocking);
 
-            SocketInformation info = original.DuplicateAndClose(CurrentProcessId);
+            SocketInformation info = original.DuplicateAndClose(Environment.ProcessId);
 
             using Socket clone = new Socket(info);
             Assert.Equal(blocking, clone.Blocking);
@@ -112,7 +104,7 @@ namespace System.Net.Sockets.Tests
         public void DuplicateAndClose_Unix_ThrowsPlatformNotSupportedException()
         {
             using Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
-            int processId = CurrentProcessId;
+            int processId = Environment.ProcessId;
 
             Assert.Throws<PlatformNotSupportedException>(() => socket.DuplicateAndClose(processId));
         }
@@ -127,11 +119,11 @@ namespace System.Net.Sockets.Tests
 
             using Socket client0 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
 
-            using Socket client1 = new Socket(client0.DuplicateAndClose(CurrentProcessId));
+            using Socket client1 = new Socket(client0.DuplicateAndClose(Environment.ProcessId));
             Assert.False(client1.Connected);
             client1.Connect(listener.LocalEndPoint);
 
-            using Socket client2 = new Socket(client1.DuplicateAndClose(CurrentProcessId));
+            using Socket client2 = new Socket(client1.DuplicateAndClose(Environment.ProcessId));
             Assert.True(client2.Connected);
 
             using Socket handler = await listener.AcceptAsync();
@@ -151,7 +143,7 @@ namespace System.Net.Sockets.Tests
             listener0.Bind(new IPEndPoint(IPAddress.Loopback, 0));
             listener0.Listen(1);
 
-            using Socket listener1 = new Socket(listener0.DuplicateAndClose(CurrentProcessId));
+            using Socket listener1 = new Socket(listener0.DuplicateAndClose(Environment.ProcessId));
 
             using Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
             await client.ConnectAsync(listener1.LocalEndPoint);
@@ -182,7 +174,7 @@ namespace System.Net.Sockets.Tests
                 listenerProto.Listen(1);
                 EndPoint ep = listenerProto.LocalEndPoint;
 
-                using Socket listenerDuplicate = new Socket(listenerProto.DuplicateAndClose(CurrentProcessId));
+                using Socket listenerDuplicate = new Socket(listenerProto.DuplicateAndClose(Environment.ProcessId));
 
                 using var serverPipe = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable);
 
@@ -228,7 +220,7 @@ namespace System.Net.Sockets.Tests
 
                 await originalServer.ReceiveAsync(_receiveBuffer, SocketFlags.None);
 
-                SocketInformation info = originalServer.DuplicateAndClose(CurrentProcessId);
+                SocketInformation info = originalServer.DuplicateAndClose(Environment.ProcessId);
 
                 using Socket cloneServer = new Socket(info);
                 await Assert.ThrowsAsync<InvalidOperationException>(() =>
@@ -243,7 +235,7 @@ namespace System.Net.Sockets.Tests
             if (!Socket.OSSupportsUnixDomainSockets) return;
 
             using Socket original = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
-            SocketInformation info = original.DuplicateAndClose(CurrentProcessId);
+            SocketInformation info = original.DuplicateAndClose(Environment.ProcessId);
             Assert.ThrowsAny<NotSupportedException>(() => _ = new Socket(info));
         }
 
@@ -331,7 +323,7 @@ namespace System.Net.Sockets.Tests
                 if (sameProcess)
                 {
                     Task handlerCode = Task.Run(() => HandlerServerCode(_ipcPipeName));
-                    RunCommonHostLogic(CurrentProcessId);
+                    RunCommonHostLogic(Environment.ProcessId);
                     await handlerCode;
                 }
                 else
index 739a031..a5422ab 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\StandardOleMarshalObject.Windows.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Versioning\VersioningHelper.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimerQueue.Windows.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\StandardOleMarshalObject.Unix.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Versioning\VersioningHelper.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Unix.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Threading\TimerQueue.Unix.cs" />
index 31bd335..273d04b 100644 (file)
@@ -60,6 +60,8 @@ namespace System
             }
         }
 
+        private static int GetCurrentProcessId() => Interop.Sys.GetPid();
+
         internal const string NewLineConst = "\n";
 
         public static string SystemDirectory => GetFolderPathCore(SpecialFolder.System, SpecialFolderOption.None);
index ac98739..751747b 100644 (file)
@@ -86,6 +86,8 @@ namespace System
             Interop.Kernel32.GetComputerName() ??
             throw new InvalidOperationException(SR.InvalidOperation_ComputerName);
 
+        private static int GetCurrentProcessId() => unchecked((int)Interop.Kernel32.GetCurrentProcessId());
+
         private static unsafe OperatingSystem GetOSVersion()
         {
             if (Interop.NtDll.RtlGetVersionEx(out Interop.NtDll.RTL_OSVERSIONINFOEX osvi) != 0)
index f287b7e..c971a01 100644 (file)
@@ -117,6 +117,24 @@ namespace System
             return GetFolderPathCore(folder, option);
         }
 
+        private static int s_processId;
+        private static volatile bool s_haveProcessId;
+
+        /// <summary>Gets the unique identifier for the current process.</summary>
+        public static int ProcessId
+        {
+            get
+            {
+                if (!s_haveProcessId)
+                {
+                    s_processId = GetCurrentProcessId();
+                    s_haveProcessId = true;
+                }
+
+                return s_processId;
+            }
+        }
+
         public static bool Is64BitProcess => IntPtr.Size == 8;
 
         public static bool Is64BitOperatingSystem => Is64BitProcess || Is64BitOperatingSystemWhen32BitProcess;
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.Unix.cs
deleted file mode 100644 (file)
index c4ed0a9..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Runtime.Versioning
-{
-    public static partial class VersioningHelper
-    {
-        private static int GetCurrentProcessId() => Interop.Sys.GetPid();
-    }
-}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/VersioningHelper.Windows.cs
deleted file mode 100644 (file)
index aa876d7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-namespace System.Runtime.Versioning
-{
-    public static partial class VersioningHelper
-    {
-        private static int GetCurrentProcessId() => unchecked((int)Interop.Kernel32.GetCurrentProcessId());
-    }
-}
index 7a4363f..b552a4c 100644 (file)
@@ -50,7 +50,7 @@ namespace System.Runtime.Versioning
             {
                 safeName.Append(separator);
                 safeName.Append('p');
-                safeName.Append(GetCurrentProcessId());
+                safeName.Append(Environment.ProcessId);
             }
             if ((requires & SxSRequirements.CLRInstanceID) != 0)
             {
index 86cffe4..19bd4cd 100644 (file)
@@ -60,6 +60,20 @@ namespace System.Tests
             Assert.Equal(Environment.CurrentManagedThreadId, Environment.CurrentManagedThreadId);
         }
 
+        [Fact]
+        public void ProcessId_Idempotent()
+        {
+            Assert.InRange(Environment.ProcessId, 1, int.MaxValue);
+            Assert.Equal(Environment.ProcessId, Environment.ProcessId);
+        }
+
+        [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
+        public void ProcessId_MatchesExpectedValue()
+        {
+            using RemoteInvokeHandle handle = RemoteExecutor.Invoke(() => Console.WriteLine(Environment.ProcessId), new RemoteInvokeOptions { StartInfo = new ProcessStartInfo { RedirectStandardOutput = true } });
+            Assert.Equal(handle.Process.Id, int.Parse(handle.Process.StandardOutput.ReadToEnd()));
+        }
+
         [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))]
         public void CurrentManagedThreadId_DifferentForActiveThreads()
         {
index 4d70863..80a78a0 100644 (file)
@@ -1869,6 +1869,7 @@ namespace System
         public static string MachineName { get { throw null; } }
         public static string NewLine { get { throw null; } }
         public static System.OperatingSystem OSVersion { get { throw null; } }
+        public static int ProcessId { get { throw null; } }
         public static int ProcessorCount { get { throw null; } }
         public static string StackTrace { get { throw null; } }
         public static string SystemDirectory { get { throw null; } }