Nullable annotate System.Diagnostics.Process (#31671)
authorEirik Tsarpalis <eirik.tsarpalis@gmail.com>
Thu, 6 Feb 2020 18:18:48 +0000 (18:18 +0000)
committerGitHub <noreply@github.com>
Thu, 6 Feb 2020 18:18:48 +0000 (18:18 +0000)
* nullable annotate System.Diagnostics.Process

* add annotations to unix source files

* annotate remainder of non-windows implementations

* enable nullable annotation for file

* add nullable directive to cgroups.cs

* add missing nullable directives in shared files

* enable nullable annotations for ReusableTextReader

* add missing #nullable enable directives in shared files

* address feedback

* address feedback

* ensure ComputerName property is non-nullable

* assert non-nullability for specific Process.Start() overloads

42 files changed:
src/libraries/Common/src/Interop/FreeBSD/Interop.Process.cs
src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs
src/libraries/Common/src/Interop/Linux/procfs/Interop.ProcFsStat.cs
src/libraries/Common/src/Interop/OSX/Interop.libproc.cs
src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs
src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupList.cs
src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateProcessWithLogon.cs
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs
src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ProcessWaitHandle.cs
src/libraries/Common/src/System/Runtime/Serialization/SerializationGuard.cs
src/libraries/Common/src/System/Text/ReusableTextReader.cs
src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.cs
src/libraries/System.Diagnostics.Process/ref/System.Diagnostics.Process.csproj
src/libraries/System.Diagnostics.Process/src/Microsoft/Win32/SafeHandles/SafeProcessHandle.Unix.cs
src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj
src/libraries/System.Diagnostics.Process/src/System/Collections/Specialized/DictionaryWrapper.cs
src/libraries/System.Diagnostics.Process/src/System/Collections/Specialized/StringDictionaryWrapper.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/DataReceivedEventArgs.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/PerformanceCounterLib.cs
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.Linux.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.NonUap.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Unix.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.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.BSD.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.FreeBSD.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Linux.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.OSX.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Unix.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Win32.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessManager.Windows.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessModule.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessModuleCollection.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Win32.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.Windows.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessStartInfo.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessThreadCollection.cs
src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs

index 056a893..efb7567 100644 (file)
@@ -256,7 +256,7 @@ internal static partial class Interop
         /// Gets executable name for process given it's PID
         /// </summary>
         /// <param name="pid">The PID of the process</param>
-        public static unsafe string GetProcPath(int pid)
+        public static unsafe string? GetProcPath(int pid)
         {
             Span<int> sysctlName = stackalloc int[4];
             byte* pBuffer = null;
@@ -359,7 +359,7 @@ internal static partial class Interop
                 // Get the process information for the specified pid
                 info = new ProcessInfo();
 
-                info.ProcessName = Marshal.PtrToStringAnsi((IntPtr)kinfo->ki_comm);
+                info.ProcessName = Marshal.PtrToStringAnsi((IntPtr)kinfo->ki_comm)!;
                 info.BasePriority = kinfo->ki_nice;
                 info.VirtualBytes = (long)kinfo->ki_size;
                 info.WorkingSet = kinfo->ki_rssize;
index 186fe05..e54b984 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System;
 using System.Buffers.Text;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.IO;
 
 internal static partial class Interop
@@ -24,14 +26,14 @@ internal static partial class Interop
         private const string ProcCGroupFilePath = "/proc/self/cgroup";
 
         /// <summary>Path to the found cgroup memory limit path, or null if it couldn't be found.</summary>
-        internal static readonly string s_cgroupMemoryLimitPath = FindCGroupMemoryLimitPath();
+        internal static readonly string? s_cgroupMemoryLimitPath = FindCGroupMemoryLimitPath();
 
         /// <summary>Tries to read the memory limit from the cgroup memory location.</summary>
         /// <param name="limit">The read limit, or 0 if it couldn't be read.</param>
         /// <returns>true if the limit was read successfully; otherwise, false.</returns>
         public static bool TryGetMemoryLimit(out ulong limit)
         {
-            string path = s_cgroupMemoryLimitPath;
+            string? path = s_cgroupMemoryLimitPath;
 
             if (path != null &&
                 TryReadMemoryValueFromFile(path, out limit))
@@ -102,9 +104,9 @@ internal static partial class Interop
 
         /// <summary>Find the cgroup memory limit path.</summary>
         /// <returns>The limit path if found; otherwise, null.</returns>
-        private static string FindCGroupMemoryLimitPath()
+        private static string? FindCGroupMemoryLimitPath()
         {
-            string cgroupMemoryPath = FindCGroupPath("memory", out CGroupVersion version);
+            string? cgroupMemoryPath = FindCGroupPath("memory", out CGroupVersion version);
             if (cgroupMemoryPath != null)
             {
                 if (version == CGroupVersion.CGroup1)
@@ -126,10 +128,10 @@ internal static partial class Interop
         /// <summary>Find the cgroup path for the specified subsystem.</summary>
         /// <param name="subsystem">The subsystem, e.g. "memory".</param>
         /// <returns>The cgroup path if found; otherwise, null.</returns>
-        private static string FindCGroupPath(string subsystem, out CGroupVersion version)
+        private static string? FindCGroupPath(string subsystem, out CGroupVersion version)
         {
-            if (TryFindHierarchyMount(subsystem, out version, out string hierarchyRoot, out string hierarchyMount) &&
-                TryFindCGroupPathForSubsystem(subsystem, out string cgroupPathRelativeToMount))
+            if (TryFindHierarchyMount(subsystem, out version, out string? hierarchyRoot, out string? hierarchyMount) &&
+                TryFindCGroupPathForSubsystem(subsystem, out string? cgroupPathRelativeToMount))
             {
                 // For a host cgroup, we need to append the relative path.
                 // In a docker container, the root and relative path are the same and we don't need to append.
@@ -146,12 +148,12 @@ internal static partial class Interop
         /// <param name="root">The path of the directory in the filesystem which forms the root of this mount; null if not found.</param>
         /// <param name="path">The path of the mount point relative to the process's root directory; null if not found.</param>
         /// <returns>true if the mount was found; otherwise, null.</returns>
-        private static bool TryFindHierarchyMount(string subsystem, out CGroupVersion version, out string root, out string path)
+        private static bool TryFindHierarchyMount(string subsystem, out CGroupVersion version, [NotNullWhen(true)] out string? root, [NotNullWhen(true)] out string? path)
         {
             return TryFindHierarchyMount(ProcMountInfoFilePath, subsystem, out version, out root, out path);
         }
 
-        internal static bool TryFindHierarchyMount(string mountInfoFilePath, string subsystem, out CGroupVersion version, out string root, out string path)
+        internal static bool TryFindHierarchyMount(string mountInfoFilePath, string subsystem, out CGroupVersion version, [NotNullWhen(true)] out string? root, [NotNullWhen(true)] out string? path)
         {
             if (File.Exists(mountInfoFilePath))
             {
@@ -159,7 +161,7 @@ internal static partial class Interop
                 {
                     using (var reader = new StreamReader(mountInfoFilePath))
                     {
-                        string line;
+                        string? line;
                         while ((line = reader.ReadLine()) != null)
                         {
                             // Look for an entry that has cgroup as the "filesystem type"
@@ -235,12 +237,12 @@ internal static partial class Interop
         /// <param name="subsystem">The subsystem, e.g. "memory".</param>
         /// <param name="path">The found path, or null if it couldn't be found.</param>
         /// <returns></returns>
-        private static bool TryFindCGroupPathForSubsystem(string subsystem, out string path)
+        private static bool TryFindCGroupPathForSubsystem(string subsystem, [NotNullWhen(true)] out string? path)
         {
             return TryFindCGroupPathForSubsystem(ProcCGroupFilePath, subsystem, out path);
         }
 
-        internal static bool TryFindCGroupPathForSubsystem(string procCGroupFilePath, string subsystem, out string path)
+        internal static bool TryFindCGroupPathForSubsystem(string procCGroupFilePath, string subsystem, [NotNullWhen(true)] out string? path)
         {
             if (File.Exists(procCGroupFilePath))
             {
@@ -248,7 +250,7 @@ internal static partial class Interop
                 {
                     using (var reader = new StreamReader(procCGroupFilePath))
                     {
-                        string line;
+                        string? line;
                         while ((line = reader.ReadLine()) != null)
                         {
                             string[] lineParts = line.Split(':');
index 98c5b0d..b61ad75 100644 (file)
@@ -2,9 +2,11 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.IO;
 using System.Text;
@@ -243,7 +245,7 @@ internal static partial class Interop
 
         internal static bool TryParseStatFile(string statFilePath, out ParsedStat result, ReusableTextReader reusableReader)
         {
-            if (!TryReadFile(statFilePath, reusableReader, out string statFileContents))
+            if (!TryReadFile(statFilePath, reusableReader, out string? statFileContents))
             {
                 // 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.
@@ -312,7 +314,7 @@ internal static partial class Interop
 
         internal static bool TryParseStatusFile(string statusFilePath, out ParsedStatus result, ReusableTextReader reusableReader)
         {
-            if (!TryReadFile(statusFilePath, reusableReader, out string fileContents))
+            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.
@@ -415,7 +417,7 @@ internal static partial class Interop
             return true;
         }
 
-        private static bool TryReadFile(string filePath, ReusableTextReader reusableReader, out string fileContents)
+        private static bool TryReadFile(string filePath, ReusableTextReader reusableReader, [NotNullWhen(true)] out string? fileContents)
         {
             try
             {
index 6775b4d..07d9a42 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
+
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
@@ -362,7 +364,7 @@ internal static partial class Interop
 
             int result = 0;
             int size = 20; // start assuming 20 threads is enough
-            ulong[] threadIds = null;
+            ulong[]? threadIds = null;
             var threads = new List<KeyValuePair<ulong, proc_threadinfo?>>();
 
             // We have no way of knowing how many threads the process has (and therefore how big our buffer should be)
index e6300cb..2c835e9 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
+
 using System;
 using System.ComponentModel;
 using System.Diagnostics;
@@ -13,9 +15,9 @@ internal static partial class Interop
     internal static partial class Sys
     {
         internal static unsafe int ForkAndExecProcess(
-            string filename, string[] argv, string[] envp, string cwd,
+            string filename, string[] argv, string[] envp, string? cwd,
             bool redirectStdin, bool redirectStdout, bool redirectStderr,
-            bool setUser, uint userId, uint groupId, uint[] groups,
+            bool setUser, uint userId, uint groupId, uint[]? groups,
             out int lpChildPid, out int stdinFd, out int stdoutFd, out int stderrFd, bool shouldThrow = true)
         {
             byte** argvPtr = null, envpPtr = null;
@@ -43,7 +45,7 @@ internal static partial class Interop
 
         [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ForkAndExecProcess", SetLastError = true)]
         private static extern unsafe int ForkAndExecProcess(
-            string filename, byte** argv, byte** envp, string cwd,
+            string filename, byte** argv, byte** envp, string? cwd,
             int redirectStdin, int redirectStdout, int redirectStderr,
             int setUser, uint userId, uint groupId, uint* groups, int groupsLength,
             out int lpChildPid, out int stdinFd, out int stdoutFd, out int stderrFd);
index adf74ce..0d85e12 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
+
 using System;
 using System.Runtime.InteropServices;
 
@@ -9,7 +11,7 @@ internal static partial class Interop
 {
     internal static partial class Sys
     {
-        internal static unsafe uint[] GetGroupList(string userName, uint primaryGroupId)
+        internal static unsafe uint[]? GetGroupList(string userName, uint primaryGroupId)
         {
             const int InitialGroupsLength =
 #if DEBUG
index 57cf23e..fdf8eb6 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
+
 using System;
 using System.Runtime.InteropServices;
 using System.Text;
@@ -16,7 +18,7 @@ internal partial class Interop
             string domain,
             IntPtr password,
             LogonFlags logonFlags,
-            string appName,
+            string? appName,
             [In] StringBuilder cmdLine,
             int creationFlags,
             IntPtr environmentBlock,
index 0de42d7..c90bdbf 100644 (file)
@@ -2,6 +2,8 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
+
 using Microsoft.Win32.SafeHandles;
 using System;
 using System.Runtime.InteropServices;
@@ -13,7 +15,7 @@ internal partial class Interop
     {
         [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "CreateProcessW")]
         internal static extern bool CreateProcess(
-            string lpApplicationName,
+            string? lpApplicationName,
             [In] StringBuilder lpCommandLine,
             ref SECURITY_ATTRIBUTES procSecAttrs,
             ref SECURITY_ATTRIBUTES threadSecAttrs,
index 8fab26c..94c996c 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+#nullable enable
 using Microsoft.Win32.SafeHandles;
 using System.Runtime.InteropServices;
 using System.Threading;
@@ -14,7 +15,7 @@ internal partial class Interop
         {
             internal ProcessWaitHandle(SafeProcessHandle processHandle)
             {
-                SafeWaitHandle waitHandle = null;
+                SafeWaitHandle? waitHandle;
                 SafeProcessHandle currentProcHandle = Interop.Kernel32.GetCurrentProcess();
                 bool succeeded = Interop.Kernel32.DuplicateHandle(
                     currentProcHandle,
index 72ededa..3fa5f3f 100644 (file)
@@ -12,16 +12,16 @@ namespace System.Runtime.Serialization
     internal static partial class SerializationGuard
     {
         private delegate void ThrowIfDeserializationInProgressWithSwitchDel(string switchName, ref int cachedValue);
-        private static readonly ThrowIfDeserializationInProgressWithSwitchDel s_throwIfDeserializationInProgressWithSwitch = CreateThrowIfDeserializationInProgressWithSwitchDelegate();
+        private static readonly ThrowIfDeserializationInProgressWithSwitchDel? s_throwIfDeserializationInProgressWithSwitch = CreateThrowIfDeserializationInProgressWithSwitchDelegate();
 
         /// <summary>
         /// Builds a wrapper delegate for SerializationInfo.ThrowIfDeserializationInProgress(string, ref int),
         /// since it is not exposed via contracts.
         /// </summary>
-        private static ThrowIfDeserializationInProgressWithSwitchDel CreateThrowIfDeserializationInProgressWithSwitchDelegate()
+        private static ThrowIfDeserializationInProgressWithSwitchDel? CreateThrowIfDeserializationInProgressWithSwitchDelegate()
         {
-            ThrowIfDeserializationInProgressWithSwitchDel throwIfDeserializationInProgressDelegate = null;
-            MethodInfo throwMethod = typeof(SerializationInfo).GetMethod("ThrowIfDeserializationInProgress",
+            ThrowIfDeserializationInProgressWithSwitchDel? throwIfDeserializationInProgressDelegate = null;
+            MethodInfo? throwMethod = typeof(SerializationInfo).GetMethod("ThrowIfDeserializationInProgress",
                 BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, new Type[] { typeof(string), typeof(int).MakeByRefType() }, Array.Empty<ParameterModifier>());
 
             if (throwMethod != null)
index 1686cf0..0cb7030 100644 (file)
@@ -4,6 +4,8 @@
 
 using System.IO;
 
+#nullable enable
+
 namespace System.Text
 {
     /// <summary>Provides a reusable reader for reading all of the text from streams.</summary>
@@ -21,7 +23,7 @@ namespace System.Text
         /// <summary>Initializes a new reusable reader.</summary>
         /// <param name="encoding">The Encoding to use.  Defaults to UTF8.</param>
         /// <param name="bufferSize">The size of the buffer to use when reading from the stream.</param>
-        public ReusableTextReader(Encoding encoding = null, int bufferSize = 1024)
+        public ReusableTextReader(Encoding? encoding = null, int bufferSize = 1024)
         {
             if (encoding == null)
             {
index 6d411ca..95c3aa4 100644 (file)
@@ -10,7 +10,6 @@ namespace Microsoft.Win32.SafeHandles
     public sealed partial class SafeProcessHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
     {
         public SafeProcessHandle(System.IntPtr existingHandle, bool ownsHandle) : base (default(bool)) { }
-        public override bool IsInvalid { get { throw null; } }
         protected override bool ReleaseHandle() { throw null; }
     }
 }
@@ -19,7 +18,7 @@ namespace System.Diagnostics
     public partial class DataReceivedEventArgs : System.EventArgs
     {
         internal DataReceivedEventArgs() { }
-        public string Data { get { throw null; } }
+        public string? Data { get { throw null; } }
     }
     public delegate void DataReceivedEventHandler(object sender, System.Diagnostics.DataReceivedEventArgs e);
     [System.AttributeUsageAttribute(System.AttributeTargets.All)]
@@ -28,7 +27,7 @@ namespace System.Diagnostics
         public MonitoringDescriptionAttribute(string description) { }
         public override string Description { get { throw null; } }
     }
-    public partial class Process : System.ComponentModel.Component
+    public partial class Process : System.ComponentModel.Component, System.IDisposable
     {
         public Process() { }
         public int BasePriority { get { throw null; } }
@@ -40,7 +39,7 @@ namespace System.Diagnostics
         public bool HasExited { get { throw null; } }
         public int Id { get { throw null; } }
         public string MachineName { get { throw null; } }
-        public System.Diagnostics.ProcessModule MainModule { get { throw null; } }
+        public System.Diagnostics.ProcessModule? MainModule { get { throw null; } }
         public System.IntPtr MainWindowHandle { get { throw null; } }
         public string MainWindowTitle { get { throw null; } }
         public System.IntPtr MaxWorkingSet { get { throw null; } set { } }
@@ -80,7 +79,7 @@ namespace System.Diagnostics
         public System.IO.StreamReader StandardOutput { get { throw null; } }
         public System.Diagnostics.ProcessStartInfo StartInfo { get { throw null; } set { } }
         public System.DateTime StartTime { get { throw null; } }
-        public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { get { throw null; } set { } }
+        public System.ComponentModel.ISynchronizeInvoke? SynchronizingObject { get { throw null; } set { } }
         public System.Diagnostics.ProcessThreadCollection Threads { get { throw null; } }
         public System.TimeSpan TotalProcessorTime { get { throw null; } }
         public System.TimeSpan UserProcessorTime { get { throw null; } }
@@ -90,9 +89,9 @@ namespace System.Diagnostics
         [System.ObsoleteAttribute("This property has been deprecated.  Please use System.Diagnostics.Process.WorkingSet64 instead.  https://go.microsoft.com/fwlink/?linkid=14202")]
         public int WorkingSet { get { throw null; } }
         public long WorkingSet64 { get { throw null; } }
-        public event System.Diagnostics.DataReceivedEventHandler ErrorDataReceived { add { } remove { } }
+        public event System.Diagnostics.DataReceivedEventHandler? ErrorDataReceived { add { } remove { } }
         public event System.EventHandler Exited { add { } remove { } }
-        public event System.Diagnostics.DataReceivedEventHandler OutputDataReceived { add { } remove { } }
+        public event System.Diagnostics.DataReceivedEventHandler? OutputDataReceived { add { } remove { } }
         public void BeginErrorReadLine() { }
         public void BeginOutputReadLine() { }
         public void CancelErrorRead() { }
@@ -106,15 +105,15 @@ namespace System.Diagnostics
         public static System.Diagnostics.Process GetProcessById(int processId, string machineName) { throw null; }
         public static System.Diagnostics.Process[] GetProcesses() { throw null; }
         public static System.Diagnostics.Process[] GetProcesses(string machineName) { throw null; }
-        public static System.Diagnostics.Process[] GetProcessesByName(string processName) { throw null; }
-        public static System.Diagnostics.Process[] GetProcessesByName(string processName, string machineName) { throw null; }
+        public static System.Diagnostics.Process[] GetProcessesByName(string? processName) { throw null; }
+        public static System.Diagnostics.Process[] GetProcessesByName(string? processName, string machineName) { throw null; }
         public void Kill() { }
         public void Kill(bool entireProcessTree) { }
         public static void LeaveDebugMode() { }
         protected void OnExited() { }
         public void Refresh() { }
         public bool Start() { throw null; }
-        public static System.Diagnostics.Process Start(System.Diagnostics.ProcessStartInfo startInfo) { throw null; }
+        public static System.Diagnostics.Process? Start(System.Diagnostics.ProcessStartInfo startInfo) { throw null; }
         public static System.Diagnostics.Process Start(string fileName) { throw null; }
         public static System.Diagnostics.Process Start(string fileName, string arguments) { throw null; }
         [System.CLSCompliantAttribute(false)]
@@ -132,10 +131,10 @@ namespace System.Diagnostics
         internal ProcessModule() { }
         public System.IntPtr BaseAddress { get { throw null; } }
         public System.IntPtr EntryPointAddress { get { throw null; } }
-        public string FileName { get { throw null; } }
+        public string? FileName { get { throw null; } }
         public System.Diagnostics.FileVersionInfo FileVersionInfo { get { throw null; } }
         public int ModuleMemorySize { get { throw null; } }
-        public string ModuleName { get { throw null; } }
+        public string? ModuleName { get { throw null; } }
         public override string ToString() { throw null; }
     }
     public partial class ProcessModuleCollection : System.Collections.ReadOnlyCollectionBase
@@ -165,21 +164,21 @@ namespace System.Diagnostics
         public string Arguments { get { throw null; } set { } }
         public bool CreateNoWindow { get { throw null; } set { } }
         public string Domain { get { throw null; } set { } }
-        public System.Collections.Generic.IDictionary<string, string> Environment { get { throw null; } }
+        public System.Collections.Generic.IDictionary<string, string?> Environment { get { throw null; } }
         public System.Collections.Specialized.StringDictionary EnvironmentVariables { get { throw null; } }
         public bool ErrorDialog { get { throw null; } set { } }
         public System.IntPtr ErrorDialogParentHandle { get { throw null; } set { } }
         public string FileName { get { throw null; } set { } }
         public bool LoadUserProfile { get { throw null; } set { } }
         [System.CLSCompliantAttribute(false)]
-        public System.Security.SecureString Password { get { throw null; } set { } }
-        public string PasswordInClearText { get { throw null; } set { } }
+        public System.Security.SecureString? Password { get { throw null; } set { } }
+        public string? PasswordInClearText { get { throw null; } set { } }
         public bool RedirectStandardError { get { throw null; } set { } }
         public bool RedirectStandardInput { get { throw null; } set { } }
         public bool RedirectStandardOutput { get { throw null; } set { } }
-        public System.Text.Encoding StandardErrorEncoding { get { throw null; } set { } }
-        public System.Text.Encoding StandardInputEncoding { get { throw null; } set { } }
-        public System.Text.Encoding StandardOutputEncoding { get { throw null; } set { } }
+        public System.Text.Encoding? StandardErrorEncoding { get { throw null; } set { } }
+        public System.Text.Encoding? StandardInputEncoding { get { throw null; } set { } }
+        public System.Text.Encoding? StandardOutputEncoding { get { throw null; } set { } }
         public string UserName { get { throw null; } set { } }
         public bool UseShellExecute { get { throw null; } set { } }
         [System.ComponentModel.DefaultValueAttribute("")]
index aa90e23..e300753 100644 (file)
@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFrameworks>$(NetCoreAppCurrent)</TargetFrameworks>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="System.Diagnostics.Process.cs" />
index cbd8bd1..798e8f2 100644 (file)
@@ -24,7 +24,7 @@ namespace Microsoft.Win32.SafeHandles
         // Process.{Safe}Handle to initalize and use a WaitHandle to successfully use it on
         // Unix as well to wait for the process to complete.
 
-        private readonly SafeWaitHandle _handle;
+        private readonly SafeWaitHandle _handle = null!;
         private readonly bool _releaseRef;
 
         internal SafeProcessHandle(int processId, SafeWaitHandle handle) :
index a9ff79c..dafbb77 100644 (file)
@@ -6,6 +6,7 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <NoWarn>$(NoWarn);CS1573</NoWarn>
     <TargetFrameworks>$(NetCoreAppCurrent)-FreeBSD;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-Windows_NT</TargetFrameworks>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(TargetsFreeBSD)' == 'true' or '$(TargetsUnknownUnix)' == 'true' ">
     <!-- Suppress unused field warnings when using PlatformNotSupportedException stubs -->
index 51616e1..5b53524 100644 (file)
@@ -6,29 +6,29 @@ using System.Collections.Generic;
 
 namespace System.Collections.Specialized
 {
-    internal sealed class DictionaryWrapper : IDictionary<string, string>, IDictionary
+    internal sealed class DictionaryWrapper : IDictionary<string, string?>, IDictionary
     {
-        private readonly Dictionary<string, string> _contents;
+        private readonly Dictionary<string, string?> _contents;
 
-        public DictionaryWrapper(Dictionary<string, string> contents)
+        public DictionaryWrapper(Dictionary<string, string?> contents)
         {
             _contents = contents;
         }
 
-        public string this[string key]
+        public string? this[string key]
         {
             get => _contents[key];
             set => _contents[key] = value;
         }
 
-        public object this[object key]
+        public object? this[object key]
         {
             get => this[(string)key];
-            set => this[(string)key] = (string)value;
+            set => this[(string)key] = (string?)value;
         }
 
         public ICollection<string> Keys => _contents.Keys;
-        public ICollection<string> Values => _contents.Values;
+        public ICollection<string?> Values => _contents.Values;
 
         ICollection IDictionary.Keys => _contents.Keys;
         ICollection IDictionary.Values => _contents.Values;
@@ -40,26 +40,26 @@ namespace System.Collections.Specialized
         public bool IsFixedSize => ((IDictionary)_contents).IsFixedSize;
         public object SyncRoot => ((IDictionary)_contents).SyncRoot;
 
-        public void Add(string key, string value) => this[key] = value;
+        public void Add(string key, string? value) => this[key] = value;
 
-        public void Add(KeyValuePair<string, string> item) => Add(item.Key, item.Value);
+        public void Add(KeyValuePair<string, string?> item) => Add(item.Key, item.Value);
 
-        public void Add(object key, object value) => Add((string)key, (string)value);
+        public void Add(object key, object? value) => Add((string)key, (string?)value);
 
         public void Clear() => _contents.Clear();
 
-        public bool Contains(KeyValuePair<string, string> item)
+        public bool Contains(KeyValuePair<string, string?> item)
         {
             return _contents.ContainsKey(item.Key) && _contents[item.Key] == item.Value;
         }
 
         public bool Contains(object key) => ContainsKey((string)key);
         public bool ContainsKey(string key) => _contents.ContainsKey(key);
-        public bool ContainsValue(string value) => _contents.ContainsValue(value);
+        public bool ContainsValue(string? value) => _contents.ContainsValue(value);
 
-        public void CopyTo(KeyValuePair<string, string>[] array, int arrayIndex)
+        public void CopyTo(KeyValuePair<string, string?>[] array, int arrayIndex)
         {
-            ((IDictionary<string, string>)_contents).CopyTo(array, arrayIndex);
+            ((IDictionary<string, string?>)_contents).CopyTo(array, arrayIndex);
         }
 
         public void CopyTo(Array array, int index) => ((IDictionary)_contents).CopyTo(array, index);
@@ -67,7 +67,7 @@ namespace System.Collections.Specialized
         public bool Remove(string key) => _contents.Remove(key);
         public void Remove(object key) => Remove((string)key);
 
-        public bool Remove(KeyValuePair<string, string> item)
+        public bool Remove(KeyValuePair<string, string?> item)
         {
             if (!Contains(item))
             {
@@ -77,9 +77,9 @@ namespace System.Collections.Specialized
             return Remove(item.Key);
         }
 
-        public bool TryGetValue(string key, out string value) => _contents.TryGetValue(key, out value);
+        public bool TryGetValue(string key, out string? value) => _contents.TryGetValue(key, out value);
 
-        public IEnumerator<KeyValuePair<string, string>> GetEnumerator() => _contents.GetEnumerator();
+        public IEnumerator<KeyValuePair<string, string?>> GetEnumerator() => _contents.GetEnumerator();
         IEnumerator IEnumerable.GetEnumerator() => _contents.GetEnumerator();
         IDictionaryEnumerator IDictionary.GetEnumerator() => _contents.GetEnumerator();
     }
index a032be8..191a102 100644 (file)
@@ -18,7 +18,7 @@ namespace System.Collections.Specialized
             _contents = contents;
         }
 
-        public override string this[string key]
+        public override string? this[string key]
         {
             get { return _contents[key]; }
             set { _contents[key] = value; }
@@ -33,7 +33,7 @@ namespace System.Collections.Specialized
 
         public override object SyncRoot => _contents.SyncRoot;
 
-        public override void Add(string key, string value)
+        public override void Add(string key, string? value)
         {
             if (_contents.ContainsKey(key))
             {
@@ -47,13 +47,13 @@ namespace System.Collections.Specialized
 
         public override bool ContainsKey(string key) => _contents.ContainsKey(key);
 
-        public override bool ContainsValue(string value) => _contents.ContainsValue(value);
+        public override bool ContainsValue(string? value) => _contents.ContainsValue(value);
 
         public override void CopyTo(Array array, int index) => _contents.CopyTo(array, index);
 
         public override IEnumerator GetEnumerator()
         {
-            foreach (KeyValuePair<string, string> keyValuePair in _contents)
+            foreach (KeyValuePair<string, string?> keyValuePair in _contents)
             {
                 yield return new DictionaryEntry(keyValuePair.Key, keyValuePair.Value);
             }
@@ -61,4 +61,4 @@ namespace System.Collections.Specialized
 
         public override void Remove(string key) => _contents.Remove(key);
     }
-}
\ No newline at end of file
+}
index 35a82c6..b6cabe9 100644 (file)
@@ -31,12 +31,12 @@ namespace System.Diagnostics
         private readonly char[] _charBuffer;
 
         // Delegate to call user function.
-        private readonly Action<string> _userCallBack;
+        private readonly Action<string?> _userCallBack;
 
         private readonly CancellationTokenSource _cts;
-        private Task _readToBufferTask;
-        private readonly Queue<string> _messageQueue;
-        private StringBuilder _sb;
+        private Task? _readToBufferTask;
+        private readonly Queue<string?> _messageQueue;
+        private StringBuilder? _sb;
         private bool _bLastCarriageReturn;
         private bool _cancelOperation;
 
@@ -46,7 +46,7 @@ namespace System.Diagnostics
         // Creates a new AsyncStreamReader for the given stream. The
         // character encoding is set by encoding and the buffer size,
         // in number of 16-bit characters, is set by bufferSize.
-        internal AsyncStreamReader(Stream stream, Action<string> callback, Encoding encoding)
+        internal AsyncStreamReader(Stream stream, Action<string?> callback, Encoding encoding)
         {
             Debug.Assert(stream != null && encoding != null && callback != null, "Invalid arguments!");
             Debug.Assert(stream.CanRead, "Stream must be readable!");
@@ -62,7 +62,7 @@ namespace System.Diagnostics
             _charBuffer = new char[maxCharsPerBuffer];
 
             _cts = new CancellationTokenSource();
-            _messageQueue = new Queue<string>();
+            _messageQueue = new Queue<string?>();
         }
 
         // User calls BeginRead to start the asynchronous read
@@ -98,7 +98,7 @@ namespace System.Diagnostics
                         break;
 
                     int charLen = _decoder.GetChars(_byteBuffer, 0, bytesRead, _charBuffer, 0);
-                    _sb.Append(_charBuffer, 0, charLen);
+                    _sb!.Append(_charBuffer, 0, charLen);
                     MoveLinesFromStringBuilderToMessageQueue();
                 }
                 catch (IOException)
@@ -128,7 +128,7 @@ namespace System.Diagnostics
             // We're at EOF, process current buffer content and flush message queue.
             lock (_messageQueue)
             {
-                if (_sb.Length != 0)
+                if (_sb!.Length != 0)
                 {
                     _messageQueue.Enqueue(_sb.ToString());
                     _sb.Length = 0;
@@ -149,7 +149,7 @@ namespace System.Diagnostics
         {
             int currentIndex = _currentLinePos;
             int lineStart = 0;
-            int len = _sb.Length;
+            int len = _sb!.Length;
 
             // skip a beginning '\n' character of new block if last block ended
             // with '\r'
@@ -221,7 +221,7 @@ namespace System.Diagnostics
                 {
                     // Get the next line (if there isn't one, we're done) and
                     // invoke the user's callback with it.
-                    string line;
+                    string? line;
                     lock (_messageQueue)
                     {
                         if (_messageQueue.Count == 0)
@@ -245,7 +245,7 @@ namespace System.Diagnostics
                 // Otherwise, let the exception propagate.
                 if (rethrowInNewThread)
                 {
-                    ThreadPool.QueueUserWorkItem(edi => ((ExceptionDispatchInfo)edi).Throw(), ExceptionDispatchInfo.Capture(e));
+                    ThreadPool.QueueUserWorkItem(edi => ((ExceptionDispatchInfo)edi!).Throw(), ExceptionDispatchInfo.Capture(e));
                     return true;
                 }
                 throw;
index b178b7a..d5b0d35 100644 (file)
@@ -8,14 +8,14 @@ namespace System.Diagnostics
 
     public class DataReceivedEventArgs : EventArgs
     {
-        private readonly string _data;
+        private readonly string? _data;
 
-        internal DataReceivedEventArgs(string data)
+        internal DataReceivedEventArgs(string? data)
         {
             _data = data;
         }
 
-        public string Data
+        public string? Data
         {
             get { return _data; }
         }
index 9a2cef5..a5e340f 100644 (file)
@@ -17,17 +17,17 @@ namespace System.Diagnostics
 {
     internal sealed class PerformanceCounterLib
     {
-        private static string s_computerName;
+        private static string? s_computerName;
 
-        private PerformanceMonitor _performanceMonitor;
+        private PerformanceMonitor? _performanceMonitor;
         private readonly string _machineName;
         private readonly string _perfLcid;
 
-        private static ConcurrentDictionary<(string machineName, string lcidString), PerformanceCounterLib> s_libraryTable;
-        private Dictionary<int, string> _nameTable;
+        private static ConcurrentDictionary<(string machineName, string lcidString), PerformanceCounterLib>? s_libraryTable;
+        private Dictionary<int, string>? _nameTable;
         private readonly object _nameTableLock = new object();
 
-        private static object s_internalSyncObject;
+        private static object? s_internalSyncObject;
 
         internal PerformanceCounterLib(string machineName, string lcid)
         {
@@ -36,7 +36,7 @@ namespace System.Diagnostics
         }
 
         /// <internalonly/>
-        internal static string ComputerName => LazyInitializer.EnsureInitialized(ref s_computerName, ref s_internalSyncObject, () => Interop.Kernel32.GetComputerName());
+        internal static string ComputerName => LazyInitializer.EnsureInitialized<string>(ref s_computerName, ref s_internalSyncObject, () => Interop.Kernel32.GetComputerName() ?? "");
 
         internal Dictionary<int, string> NameTable
         {
@@ -57,7 +57,7 @@ namespace System.Diagnostics
 
         internal string GetCounterName(int index)
         {
-            string result;
+            string? result;
             return NameTable.TryGetValue(index, out result) ? result : "";
         }
 
@@ -98,7 +98,7 @@ namespace System.Diagnostics
 
             try
             {
-                string[] names = null;
+                string[]? names = null;
                 int waitRetries = 14;   //((2^13)-1)*10ms == approximately 1.4mins
                 int waitSleep = 0;
 
@@ -192,7 +192,7 @@ namespace System.Diagnostics
         internal class PerformanceMonitor
         {
 #if FEATURE_REGISTRY
-            private RegistryKey _perfDataKey = null;
+            private RegistryKey _perfDataKey = null!; // will be initialized by Init() method
 #endif
             private readonly string _machineName;
 
@@ -230,7 +230,7 @@ namespace System.Diagnostics
 #if FEATURE_REGISTRY
                 int waitRetries = 17;   //2^16*10ms == approximately 10mins
                 int waitSleep = 0;
-                byte[] data = null;
+                byte[]? data = null;
                 int error = 0;
 
                 while (waitRetries > 0)
index 0c8fac7..4193734 100644 (file)
@@ -13,7 +13,7 @@ namespace System.Diagnostics
         /// 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)
+        public static Process[] GetProcessesByName(string? processName, string machineName)
         {
             if (processName == null)
             {
index 929f125..8fcc5d0 100644 (file)
@@ -89,7 +89,7 @@ namespace System.Diagnostics
         }
 
         // <summary>Gets execution path</summary>
-        private string GetPathToOpenFile()
+        private string? GetPathToOpenFile()
         {
             Interop.Sys.FileStatus stat;
             if (Interop.Sys.Stat("/usr/local/bin/open", out stat) == 0)
@@ -106,7 +106,7 @@ namespace System.Diagnostics
         // ---- PAL layer ends here ----
         // -----------------------------
         /// <summary>Gets the path to the current executable, or null if it could not be retrieved.</summary>
-        private static string GetExePath()
+        private static string? GetExePath()
         {
             return Interop.Process.GetProcPath(Interop.Sys.GetPid());
         }
index 7ad4c85..c2c0bd7 100644 (file)
@@ -18,7 +18,7 @@ namespace System.Diagnostics
         /// 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)
+        public static Process[] GetProcessesByName(string? processName, string machineName)
         {
             ProcessManager.ThrowIfRemoteMachine(machineName);
             if (processName == null)
@@ -106,12 +106,12 @@ namespace System.Diagnostics
             GetStat().ppid;
 
         /// <summary>Gets execution path</summary>
-        private string GetPathToOpenFile()
+        private string? GetPathToOpenFile()
         {
             string[] allowedProgramsToRun = { "xdg-open", "gnome-open", "kfmclient" };
             foreach (var program in allowedProgramsToRun)
             {
-                string pathToProgram = FindProgramInPath(program);
+                string? pathToProgram = FindProgramInPath(program);
                 if (!string.IsNullOrEmpty(pathToProgram))
                 {
                     return pathToProgram;
@@ -148,7 +148,7 @@ namespace System.Diagnostics
 
         partial void EnsureHandleCountPopulated()
         {
-            if (_processInfo.HandleCount <= 0 && _haveProcessId)
+            if (_processInfo!.HandleCount <= 0 && _haveProcessId)
             {
                 // Don't get information for a PID that exited and has possibly been recycled.
                 if (GetHasExited(refresh: false))
@@ -248,7 +248,7 @@ namespace System.Diagnostics
 
         /// <summary>Gets the path to the executable for the process, or null if it could not be retrieved.</summary>
         /// <param name="processId">The pid for the target process, or -1 for the current process.</param>
-        internal static string GetExePath(int processId = -1)
+        internal static string? GetExePath(int processId = -1)
         {
             string exeFilePath = processId == -1 ?
                 Interop.procfs.SelfExeFilePath :
@@ -263,7 +263,7 @@ namespace System.Diagnostics
         {
             string cmdLineFilePath = Interop.procfs.GetCmdLinePathForProcess(stat.pid);
 
-            byte[] rentedArray = null;
+            byte[]? rentedArray = null;
             try
             {
                 // bufferSize == 1 used to avoid unnecessary buffer in FileStream
@@ -280,7 +280,7 @@ namespace System.Diagnostics
 
                             byte[] tmp = ArrayPool<byte>.Shared.Rent((int)newLength);
                             buffer.CopyTo(tmp);
-                            byte[] toReturn = rentedArray;
+                            byte[]? toReturn = rentedArray;
                             buffer = rentedArray = tmp;
                             if (toReturn != null)
                             {
@@ -301,7 +301,7 @@ namespace System.Diagnostics
                         if (argEnd != -1)
                         {
                             // Check if argv[0] has the process name.
-                            string name = GetUntruncatedNameFromArg(argRemainder.Slice(0, argEnd), prefix: stat.comm);
+                            string? name = GetUntruncatedNameFromArg(argRemainder.Slice(0, argEnd), prefix: stat.comm);
                             if (name != null)
                             {
                                 return name;
@@ -336,7 +336,7 @@ namespace System.Diagnostics
                 }
             }
 
-            string GetUntruncatedNameFromArg(Span<byte> arg, string prefix)
+            string? GetUntruncatedNameFromArg(Span<byte> arg, string prefix)
             {
                 // Strip directory names from arg.
                 int nameStart = arg.LastIndexOf((byte)'/') + 1;
index b83ff1e..20cf872 100644 (file)
@@ -40,7 +40,7 @@ namespace System.Diagnostics
             try
             {
                 var descendantProcesses = new Queue<Process>();
-                Process current = this;
+                Process? current = this;
 
                 do
                 {
@@ -67,7 +67,7 @@ namespace System.Diagnostics
         /// <summary>
         /// Returns all immediate child processes.
         /// </summary>
-        private IReadOnlyList<Process> GetChildProcesses(Process[] processes = null)
+        private IReadOnlyList<Process> GetChildProcesses(Process[]? processes = null)
         {
             bool internallyInitializedProcesses = processes == null;
             processes = processes ?? GetProcesses();
index 75d4dd6..889f06a 100644 (file)
@@ -88,12 +88,12 @@ namespace System.Diagnostics
 
         private IEnumerable<Exception> KillTree()
         {
-            List<Exception> exceptions = null;
+            List<Exception>? exceptions = null;
             KillTree(ref exceptions);
             return exceptions ?? Enumerable.Empty<Exception>();
         }
 
-        private void KillTree(ref List<Exception> exceptions)
+        private void KillTree(ref List<Exception>? exceptions)
         {
             // If the process has exited, we can no longer determine its children.
             // If we know the process has exited, stop already.
@@ -135,7 +135,7 @@ namespace System.Diagnostics
                 childProcess.Dispose();
             }
 
-            void AddException(ref List<Exception> list, Exception e)
+            void AddException(ref List<Exception>? list, Exception e)
             {
                 if (list == null)
                 {
@@ -228,7 +228,7 @@ namespace System.Diagnostics
         }
 
         /// <summary>Gets the main module for the associated process.</summary>
-        public ProcessModule MainModule
+        public ProcessModule? MainModule
         {
             get
             {
@@ -354,7 +354,7 @@ namespace System.Diagnostics
             {
                 ThrowIfExited(refresh: true);
 
-                return _processHandle;
+                return _processHandle!;
             }
 
             EnsureState(State.HaveNonExitedId | State.IsLocal);
@@ -370,7 +370,7 @@ namespace System.Diagnostics
         {
             EnsureInitialized();
 
-            string filename;
+            string? filename;
             string[] argv;
 
             if (startInfo.UseShellExecute)
@@ -383,12 +383,12 @@ namespace System.Diagnostics
 
             int stdinFd = -1, stdoutFd = -1, stderrFd = -1;
             string[] envp = CreateEnvp(startInfo);
-            string cwd = !string.IsNullOrWhiteSpace(startInfo.WorkingDirectory) ? startInfo.WorkingDirectory : null;
+            string? cwd = !string.IsNullOrWhiteSpace(startInfo.WorkingDirectory) ? startInfo.WorkingDirectory : null;
 
             bool setCredentials = !string.IsNullOrEmpty(startInfo.UserName);
             uint userId = 0;
             uint groupId = 0;
-            uint[] groups = null;
+            uint[]? groups = null;
             if (setCredentials)
             {
                 (userId, groupId, groups) = GetUserAndGroupIds(startInfo);
@@ -484,9 +484,9 @@ namespace System.Diagnostics
         }
 
         private bool ForkAndExecProcess(
-            string filename, string[] argv, string[] envp, string cwd,
+            string? filename, string[] argv, string[] envp, string? cwd,
             bool redirectStdin, bool redirectStdout, bool redirectStderr,
-            bool setCredentials, uint userId, uint groupId, uint[] groups,
+            bool setCredentials, uint userId, uint groupId, uint[]? groups,
             out int stdinFd, out int stdoutFd, out int stderrFd,
             bool usesTerminal, bool throwOnNoExec = true)
         {
@@ -562,7 +562,7 @@ namespace System.Diagnostics
         // -----------------------------
 
         /// <summary>Finalizable holder for the underlying shared wait state object.</summary>
-        private ProcessWaitState.Holder _waitStateHolder;
+        private ProcessWaitState.Holder? _waitStateHolder;
 
         /// <summary>Size to use for redirect streams and stream readers/writers.</summary>
         private const int StreamBufferSize = 4096;
@@ -572,7 +572,7 @@ namespace System.Diagnostics
         /// <param name="resolvedExe">Resolved executable to open ProcessStartInfo.FileName</param>
         /// <param name="ignoreArguments">Don't pass ProcessStartInfo.Arguments</param>
         /// <returns>The argv array.</returns>
-        private static string[] ParseArgv(ProcessStartInfo psi, string resolvedExe = null, bool ignoreArguments = false)
+        private static string[] ParseArgv(ProcessStartInfo psi, string? resolvedExe = null, bool ignoreArguments = false)
         {
             if (string.IsNullOrEmpty(resolvedExe) &&
                 (ignoreArguments || (string.IsNullOrEmpty(psi.Arguments) && psi.ArgumentList.Count == 0)))
@@ -620,12 +620,12 @@ namespace System.Diagnostics
             return envp;
         }
 
-        private static string ResolveExecutableForShellExecute(string filename, string workingDirectory)
+        private static string? ResolveExecutableForShellExecute(string filename, string? workingDirectory)
         {
             // Determine if filename points to an executable file.
             // filename may be an absolute path, a relative path or a uri.
 
-            string resolvedFilename = null;
+            string? resolvedFilename = null;
             // filename is an absolute path
             if (Path.IsPathRooted(filename))
             {
@@ -635,7 +635,7 @@ namespace System.Diagnostics
                 }
             }
             // filename is a uri
-            else if (Uri.TryCreate(filename, UriKind.Absolute, out Uri uri))
+            else if (Uri.TryCreate(filename, UriKind.Absolute, out Uri? uri))
             {
                 if (uri.IsFile && uri.Host == "" && File.Exists(uri.LocalPath))
                 {
@@ -680,7 +680,7 @@ namespace System.Diagnostics
         /// <summary>Resolves a path to the filename passed to ProcessStartInfo. </summary>
         /// <param name="filename">The filename.</param>
         /// <returns>The resolved path. It can return null in case of URLs.</returns>
-        private static string ResolvePath(string filename)
+        private static string? ResolvePath(string filename)
         {
             // Follow the same resolution that Windows uses with CreateProcess:
             // 1. First try the exact path provided
@@ -699,12 +699,12 @@ namespace System.Diagnostics
             }
 
             // Then check the executable's directory
-            string path = GetExePath();
+            string? path = GetExePath();
             if (path != null)
             {
                 try
                 {
-                    path = Path.Combine(Path.GetDirectoryName(path), filename);
+                    path = Path.Combine(Path.GetDirectoryName(path)!, filename);
                     if (File.Exists(path))
                     {
                         return path;
@@ -729,10 +729,10 @@ namespace System.Diagnostics
         /// </summary>
         /// <param name="program"></param>
         /// <returns></returns>
-        private static string FindProgramInPath(string program)
+        private static string? FindProgramInPath(string program)
         {
             string path;
-            string pathEnvVar = Environment.GetEnvironmentVariable("PATH");
+            string? pathEnvVar = Environment.GetEnvironmentVariable("PATH");
             if (pathEnvVar != null)
             {
                 var pathParser = new StringParser(pathEnvVar, ':', skipEmpty: true);
@@ -912,7 +912,7 @@ namespace System.Diagnostics
                 throw new Win32Exception(SR.Format(SR.UserDoesNotExist, startInfo.UserName));
             }
 
-            uint[] groups = Interop.Sys.GetGroupList(startInfo.UserName, groupId.Value);
+            uint[]? groups = Interop.Sys.GetGroupList(startInfo.UserName, groupId!.Value);
             if (groups == null)
             {
                 throw new Win32Exception(SR.Format(SR.UserGroupsCannotBeDetermined, startInfo.UserName));
index e0c791c..4f2f6ac 100644 (file)
@@ -16,7 +16,7 @@ namespace System.Diagnostics
     {
         private bool _haveMainWindow;
         private IntPtr _mainWindowHandle;
-        private string _mainWindowTitle;
+        private string? _mainWindowTitle;
 
         private bool _haveResponding;
         private bool _responding;
index c720399..ec8601c 100644 (file)
@@ -21,7 +21,7 @@ namespace System.Diagnostics
         /// 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)
+        public static Process[] GetProcessesByName(string? processName, string machineName)
         {
             if (processName == null)
             {
@@ -47,7 +47,7 @@ namespace System.Diagnostics
         }
 
         [CLSCompliant(false)]
-        public static Process Start(string fileName, string userName, SecureString password, string domain)
+        public static Process? Start(string fileName, string userName, SecureString password, string domain)
         {
             ProcessStartInfo startInfo = new ProcessStartInfo(fileName);
             startInfo.UserName = userName;
@@ -58,7 +58,7 @@ namespace System.Diagnostics
         }
 
         [CLSCompliant(false)]
-        public static Process Start(string fileName, string arguments, string userName, SecureString password, string domain)
+        public static Process? Start(string fileName, string arguments, string userName, SecureString password, string domain)
         {
             ProcessStartInfo startInfo = new ProcessStartInfo(fileName, arguments);
             startInfo.UserName = userName;
@@ -159,7 +159,7 @@ namespace System.Diagnostics
         /// </summary>
         private bool WaitForExitCore(int milliseconds)
         {
-            SafeProcessHandle handle = null;
+            SafeProcessHandle? handle = null;
             try
             {
                 handle = GetProcessHandle(Interop.Advapi32.ProcessOptions.SYNCHRONIZE, false);
@@ -185,7 +185,7 @@ namespace System.Diagnostics
         }
 
         /// <summary>Gets the main module for the associated process.</summary>
-        public ProcessModule MainModule
+        public ProcessModule? MainModule
         {
             get
             {
@@ -469,12 +469,12 @@ namespace System.Diagnostics
             SafeThreadHandle threadSH = new SafeThreadHandle();
 
             // handles used in parent process
-            SafeFileHandle parentInputPipeHandle = null;
-            SafeFileHandle childInputPipeHandle = null;
-            SafeFileHandle parentOutputPipeHandle = null;
-            SafeFileHandle childOutputPipeHandle = null;
-            SafeFileHandle parentErrorPipeHandle = null;
-            SafeFileHandle childErrorPipeHandle = null;
+            SafeFileHandle? parentInputPipeHandle = null;
+            SafeFileHandle? childInputPipeHandle = null;
+            SafeFileHandle? parentOutputPipeHandle = null;
+            SafeFileHandle? childOutputPipeHandle = null;
+            SafeFileHandle? parentErrorPipeHandle = null;
+            SafeFileHandle? childErrorPipeHandle = null;
 
             // Take a global lock to synchronize all redirect pipe handle creations and CreateProcess
             // calls. We do not want one process to inherit the handles created concurrently for another
@@ -528,11 +528,11 @@ namespace System.Diagnostics
                     if (startInfo.CreateNoWindow) creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_NO_WINDOW;
 
                     // set up the environment block parameter
-                    string environmentBlock = null;
+                    string? environmentBlock = null;
                     if (startInfo._environmentVariables != null)
                     {
                         creationFlags |= Interop.Advapi32.StartupInfoOptions.CREATE_UNICODE_ENVIRONMENT;
-                        environmentBlock = GetEnvironmentVariablesBlock(startInfo._environmentVariables);
+                        environmentBlock = GetEnvironmentVariablesBlock(startInfo._environmentVariables!);
                     }
                     string workingDirectory = startInfo.WorkingDirectory;
                     if (workingDirectory == string.Empty)
@@ -633,18 +633,18 @@ namespace System.Diagnostics
             if (startInfo.RedirectStandardInput)
             {
                 Encoding enc = startInfo.StandardInputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleCP());
-                _standardInput = new StreamWriter(new FileStream(parentInputPipeHandle, FileAccess.Write, 4096, false), enc, 4096);
+                _standardInput = new StreamWriter(new FileStream(parentInputPipeHandle!, FileAccess.Write, 4096, false), enc, 4096);
                 _standardInput.AutoFlush = true;
             }
             if (startInfo.RedirectStandardOutput)
             {
                 Encoding enc = startInfo.StandardOutputEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleOutputCP());
-                _standardOutput = new StreamReader(new FileStream(parentOutputPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
+                _standardOutput = new StreamReader(new FileStream(parentOutputPipeHandle!, FileAccess.Read, 4096, false), enc, true, 4096);
             }
             if (startInfo.RedirectStandardError)
             {
                 Encoding enc = startInfo.StandardErrorEncoding ?? GetEncoding((int)Interop.Kernel32.GetConsoleOutputCP());
-                _standardError = new StreamReader(new FileStream(parentErrorPipeHandle, FileAccess.Read, 4096, false), enc, true, 4096);
+                _standardError = new StreamReader(new FileStream(parentErrorPipeHandle!, FileAccess.Read, 4096, false), enc, true, 4096);
             }
 
             if (procSH.IsInvalid)
@@ -725,7 +725,7 @@ namespace System.Diagnostics
             // this is only a "pseudo handle" to the current process - no need to close it later
             SafeProcessHandle processHandle = Interop.Kernel32.GetCurrentProcess();
 
-            SafeTokenHandle hToken = null;
+            SafeTokenHandle? hToken = null;
 
             try
             {
@@ -779,7 +779,7 @@ namespace System.Diagnostics
                     // Since haveProcessHandle is true, we know we have the process handle
                     // open with at least SYNCHRONIZE access, so we can wait on it with
                     // zero timeout to see if the process has exited.
-                    using (Interop.Kernel32.ProcessWaitHandle waitHandle = new Interop.Kernel32.ProcessWaitHandle(_processHandle))
+                    using (Interop.Kernel32.ProcessWaitHandle waitHandle = new Interop.Kernel32.ProcessWaitHandle(_processHandle!))
                     {
                         if (waitHandle.WaitOne(0))
                         {
@@ -794,7 +794,7 @@ namespace System.Diagnostics
                 // If we dispose of our contained handle we'll be in a bad state. .NET Framework dealt with this
                 // by doing a try..finally around every usage of GetProcessHandle and only disposed if
                 // it wasn't our handle.
-                return new SafeProcessHandle(_processHandle.DangerousGetHandle(), ownsHandle: false);
+                return new SafeProcessHandle(_processHandle!.DangerousGetHandle(), ownsHandle: false);
             }
             else
             {
@@ -843,7 +843,7 @@ namespace System.Diagnostics
             Interop.Kernel32.SECURITY_ATTRIBUTES securityAttributesParent = default;
             securityAttributesParent.bInheritHandle = Interop.BOOL.TRUE;
 
-            SafeFileHandle hTmp = null;
+            SafeFileHandle? hTmp = null;
             try
             {
                 if (parentInputs)
index e4de4f7..03ab377 100644 (file)
@@ -24,13 +24,13 @@ namespace System.Diagnostics
         private bool _haveProcessId;
         private int _processId;
         private bool _haveProcessHandle;
-        private SafeProcessHandle _processHandle;
+        private SafeProcessHandle? _processHandle;
         private bool _isRemoteMachine;
         private string _machineName;
-        private ProcessInfo _processInfo;
+        private ProcessInfo? _processInfo;
 
-        private ProcessThreadCollection _threads;
-        private ProcessModuleCollection _modules;
+        private ProcessThreadCollection? _threads;
+        private ProcessModuleCollection? _modules;
 
         private bool _haveWorkingSetLimits;
         private IntPtr _minWorkingSet;
@@ -42,11 +42,11 @@ namespace System.Diagnostics
         private bool _havePriorityClass;
         private ProcessPriorityClass _priorityClass;
 
-        private ProcessStartInfo _startInfo;
+        private ProcessStartInfo? _startInfo;
 
         private bool _watchForExit;
         private bool _watchingForExit;
-        private EventHandler _onExited;
+        private EventHandler? _onExited;
         private bool _exited;
         private int _exitCode;
 
@@ -58,11 +58,11 @@ namespace System.Diagnostics
         private bool _havePriorityBoostEnabled;
 
         private bool _raisedOnExited;
-        private RegisteredWaitHandle _registeredWaitHandle;
-        private WaitHandle _waitHandle;
-        private StreamReader _standardOutput;
-        private StreamWriter _standardInput;
-        private StreamReader _standardError;
+        private RegisteredWaitHandle? _registeredWaitHandle;
+        private WaitHandle? _waitHandle;
+        private StreamReader? _standardOutput;
+        private StreamWriter? _standardInput;
+        private StreamReader? _standardError;
         private bool _disposed;
 
         private bool _standardInputAccessed;
@@ -71,12 +71,12 @@ namespace System.Diagnostics
         private StreamReadMode _errorStreamReadMode;
 
         // Support for asynchronously reading streams
-        public event DataReceivedEventHandler OutputDataReceived;
-        public event DataReceivedEventHandler ErrorDataReceived;
+        public event DataReceivedEventHandler? OutputDataReceived;
+        public event DataReceivedEventHandler? ErrorDataReceived;
 
         // Abstract the stream details
-        internal AsyncStreamReader _output;
-        internal AsyncStreamReader _error;
+        internal AsyncStreamReader? _output;
+        internal AsyncStreamReader? _error;
         internal bool _pendingOutputRead;
         internal bool _pendingErrorRead;
 
@@ -103,7 +103,7 @@ namespace System.Diagnostics
             _errorStreamReadMode = StreamReadMode.Undefined;
         }
 
-        private Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo processInfo)
+        private Process(string machineName, bool isRemoteMachine, int processId, ProcessInfo? processInfo)
         {
             GC.SuppressFinalize(this);
             _processInfo = processInfo;
@@ -146,7 +146,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.BasePriority;
+                return _processInfo!.BasePriority;
             }
         }
 
@@ -307,7 +307,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.PoolNonPagedBytes;
+                return _processInfo!.PoolNonPagedBytes;
             }
         }
 
@@ -317,7 +317,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.PoolNonPagedBytes);
+                return unchecked((int)_processInfo!.PoolNonPagedBytes);
             }
         }
 
@@ -327,7 +327,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.PageFileBytes;
+                return _processInfo!.PageFileBytes;
             }
         }
 
@@ -337,7 +337,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.PageFileBytes);
+                return unchecked((int)_processInfo!.PageFileBytes);
             }
         }
 
@@ -347,7 +347,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.PoolPagedBytes;
+                return _processInfo!.PoolPagedBytes;
             }
         }
 
@@ -357,7 +357,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.PoolPagedBytes);
+                return unchecked((int)_processInfo!.PoolPagedBytes);
             }
         }
 
@@ -367,7 +367,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.PageFileBytesPeak;
+                return _processInfo!.PageFileBytesPeak;
             }
         }
 
@@ -377,7 +377,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.PageFileBytesPeak);
+                return unchecked((int)_processInfo!.PageFileBytesPeak);
             }
         }
 
@@ -386,7 +386,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.WorkingSetPeak;
+                return _processInfo!.WorkingSetPeak;
             }
         }
 
@@ -396,7 +396,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.WorkingSetPeak);
+                return unchecked((int)_processInfo!.WorkingSetPeak);
             }
         }
 
@@ -405,7 +405,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.VirtualBytesPeak;
+                return _processInfo!.VirtualBytesPeak;
             }
         }
 
@@ -415,7 +415,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.VirtualBytesPeak);
+                return unchecked((int)_processInfo!.VirtualBytesPeak);
             }
         }
 
@@ -480,7 +480,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.PrivateBytes;
+                return _processInfo!.PrivateBytes;
             }
         }
 
@@ -490,7 +490,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.PrivateBytes);
+                return unchecked((int)_processInfo!.PrivateBytes);
             }
         }
 
@@ -505,7 +505,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.ProcessName;
+                return _processInfo!.ProcessName;
             }
         }
 
@@ -539,7 +539,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.SessionId;
+                return _processInfo!.SessionId;
             }
         }
 
@@ -592,7 +592,7 @@ namespace System.Diagnostics
                 if (_threads == null)
                 {
                     EnsureState(State.HaveProcessInfo);
-                    int count = _processInfo._threadInfoList.Count;
+                    int count = _processInfo!._threadInfoList.Count;
                     ProcessThread[] newThreadsArray = new ProcessThread[count];
                     for (int i = 0; i < count; i++)
                     {
@@ -612,7 +612,7 @@ namespace System.Diagnostics
             {
                 EnsureState(State.HaveProcessInfo);
                 EnsureHandleCountPopulated();
-                return _processInfo.HandleCount;
+                return _processInfo!.HandleCount;
             }
         }
 
@@ -623,7 +623,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.VirtualBytes;
+                return _processInfo!.VirtualBytes;
             }
         }
 
@@ -633,7 +633,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.VirtualBytes);
+                return unchecked((int)_processInfo!.VirtualBytes);
             }
         }
 
@@ -743,7 +743,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return _processInfo.WorkingSet;
+                return _processInfo!.WorkingSet;
             }
         }
 
@@ -753,7 +753,7 @@ namespace System.Diagnostics
             get
             {
                 EnsureState(State.HaveProcessInfo);
-                return unchecked((int)_processInfo.WorkingSet);
+                return unchecked((int)_processInfo!.WorkingSet);
             }
         }
 
@@ -773,7 +773,7 @@ namespace System.Diagnostics
         ///     This is called from the threadpool when a process exits.
         /// </devdoc>
         /// <internalonly/>
-        private void CompletionCallback(object waitHandleContext, bool wasSignaled)
+        private void CompletionCallback(object? waitHandleContext, bool wasSignaled)
         {
             Debug.Assert(waitHandleContext != null, "Process.CompletionCallback called with no waitHandleContext");
             lock (this)
@@ -823,7 +823,7 @@ namespace System.Diagnostics
             return WaitForInputIdleCore(milliseconds);
         }
 
-        public ISynchronizeInvoke SynchronizingObject { get; set; }
+        public ISynchronizeInvoke? SynchronizingObject { get; set; }
 
         /// <devdoc>
         ///    <para>
@@ -845,7 +845,7 @@ namespace System.Diagnostics
 
                 if (_haveProcessHandle)
                 {
-                    _processHandle.Dispose();
+                    _processHandle!.Dispose();
                     _processHandle = null;
                     _haveProcessHandle = false;
                 }
@@ -918,7 +918,7 @@ namespace System.Diagnostics
                 {
                     if (_haveProcessHandle)
                     {
-                        SetProcessId(ProcessManager.GetProcessIdFromHandle(_processHandle));
+                        SetProcessId(ProcessManager.GetProcessIdFromHandle(_processHandle!));
                     }
                     else
                     {
@@ -1025,7 +1025,7 @@ namespace System.Diagnostics
         ///       local computer. These process resources share the specified process name.
         ///    </para>
         /// </devdoc>
-        public static Process[] GetProcessesByName(string processName)
+        public static Process[] GetProcessesByName(string? processName)
         {
             return GetProcessesByName(processName, ".");
         }
@@ -1079,7 +1079,7 @@ namespace System.Diagnostics
         /// </devdoc>
         protected void OnExited()
         {
-            EventHandler exited = _onExited;
+            EventHandler? exited = _onExited;
             if (exited != null)
             {
                 exited(this, EventArgs.Empty);
@@ -1143,7 +1143,7 @@ namespace System.Diagnostics
 
                 SetProcessHandle(GetProcessHandle());
             }
-            return _processHandle;
+            return _processHandle!;
         }
 
         /// <devdoc>
@@ -1229,7 +1229,10 @@ namespace System.Diagnostics
         /// </devdoc>
         public static Process Start(string fileName)
         {
-            return Start(new ProcessStartInfo(fileName));
+            // the underlying Start method can only return null on Windows platforms,
+            // when the ProcessStartInfo.UseShellExecute property is set to true.
+            // We can thus safely assert non-nullability for tihs overload.
+            return Start(new ProcessStartInfo(fileName))!;
         }
 
         /// <devdoc>
@@ -1242,7 +1245,10 @@ namespace System.Diagnostics
         /// </devdoc>
         public static Process Start(string fileName, string arguments)
         {
-            return Start(new ProcessStartInfo(fileName, arguments));
+            // the underlying Start method can only return null on Windows platforms,
+            // when the ProcessStartInfo.UseShellExecute property is set to true.
+            // We can thus safely assert non-nullability for tihs overload.
+            return Start(new ProcessStartInfo(fileName, arguments))!;
         }
 
         /// <devdoc>
@@ -1253,7 +1259,7 @@ namespace System.Diagnostics
         ///       component.
         ///    </para>
         /// </devdoc>
-        public static Process Start(ProcessStartInfo startInfo)
+        public static Process? Start(ProcessStartInfo startInfo)
         {
             Process process = new Process();
             if (startInfo == null)
@@ -1273,8 +1279,8 @@ namespace System.Diagnostics
         {
             if (_watchingForExit)
             {
-                RegisteredWaitHandle rwh = null;
-                WaitHandle wh = null;
+                RegisteredWaitHandle? rwh = null;
+                WaitHandle? wh = null;
 
                 lock (this)
                 {
@@ -1457,10 +1463,10 @@ namespace System.Diagnostics
             _pendingErrorRead = false;
         }
 
-        internal void OutputReadNotifyUser(string data)
+        internal void OutputReadNotifyUser(string? data)
         {
             // To avoid race between remove handler and raising the event
-            DataReceivedEventHandler outputDataReceived = OutputDataReceived;
+            DataReceivedEventHandler? outputDataReceived = OutputDataReceived;
             if (outputDataReceived != null)
             {
                 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
@@ -1468,10 +1474,10 @@ namespace System.Diagnostics
             }
         }
 
-        internal void ErrorReadNotifyUser(string data)
+        internal void ErrorReadNotifyUser(string? data)
         {
             // To avoid race between remove handler and raising the event
-            DataReceivedEventHandler errorDataReceived = ErrorDataReceived;
+            DataReceivedEventHandler? errorDataReceived = ErrorDataReceived;
             if (errorDataReceived != null)
             {
                 DataReceivedEventArgs e = new DataReceivedEventArgs(data);
index 1056dbf..3f03e26 100644 (file)
@@ -43,7 +43,7 @@ namespace System.Diagnostics
             // and why MainModule exists.
             try
             {
-                string exePath = GetProcPath(processId);
+                string? exePath = GetProcPath(processId);
                 if (!string.IsNullOrEmpty(exePath))
                 {
                     return new ProcessModuleCollection(1)
index 652d0f5..a1343e4 100644 (file)
@@ -16,7 +16,7 @@ namespace System.Diagnostics
             return Interop.Process.ListAllPids();
         }
 
-        internal static string GetProcPath(int processId)
+        internal static string? GetProcPath(int processId)
         {
             return Interop.Process.GetProcPath(processId);
         }
index a8dfca6..387f5c5 100644 (file)
@@ -31,7 +31,7 @@ namespace System.Diagnostics
             var processes = new List<ProcessInfo>(procIds.Length);
             foreach (int pid in procIds)
             {
-                ProcessInfo pi = CreateProcessInfo(pid, reusableReader);
+                ProcessInfo? pi = CreateProcessInfo(pid, reusableReader);
                 if (pi != null)
                 {
                     processes.Add(pi);
@@ -82,7 +82,7 @@ namespace System.Diagnostics
             }
 
             // Move the main executable module to be the first in the list if it's not already
-            string exePath = Process.GetExePath(processId);
+            string? exePath = Process.GetExePath(processId);
             for (int i = 0; i < modules.Count; i++)
             {
                 ProcessModule module = modules[i];
@@ -108,7 +108,7 @@ namespace System.Diagnostics
         /// <summary>
         /// Creates a ProcessInfo from the specified process ID.
         /// </summary>
-        internal static ProcessInfo CreateProcessInfo(int pid, ReusableTextReader reusableReader = null)
+        internal static ProcessInfo? CreateProcessInfo(int pid, ReusableTextReader? reusableReader = null)
         {
             reusableReader ??= new ReusableTextReader();
             if (Interop.procfs.TryReadStatFile(pid, out Interop.procfs.ParsedStat stat, reusableReader))
@@ -122,7 +122,7 @@ namespace System.Diagnostics
         /// <summary>
         /// Creates a ProcessInfo from the data parsed from a /proc/pid/stat file and the associated tasks directory.
         /// </summary>
-        internal static ProcessInfo CreateProcessInfo(ref Interop.procfs.ParsedStat procFsStat, ref Interop.procfs.ParsedStatus procFsStatus, ReusableTextReader reusableReader, string processName = null)
+        internal static ProcessInfo CreateProcessInfo(ref Interop.procfs.ParsedStat procFsStat, ref Interop.procfs.ParsedStatus procFsStatus, ReusableTextReader reusableReader, string? processName = null)
         {
             int pid = procFsStat.pid;
 
index dffc977..1e17703 100644 (file)
@@ -45,7 +45,7 @@ namespace System.Diagnostics
             {
                 // Set the values we have; all the other values don't have meaning or don't exist on OSX
                 Interop.libproc.proc_taskallinfo temp = info.Value;
-                unsafe { procInfo.ProcessName = Marshal.PtrToStringAnsi(new IntPtr(temp.pbsd.pbi_comm)); }
+                unsafe { procInfo.ProcessName = Marshal.PtrToStringAnsi(new IntPtr(temp.pbsd.pbi_comm))!; }
                 procInfo.BasePriority = temp.pbsd.pbi_nice;
                 procInfo.VirtualBytes = (long)temp.ptinfo.pti_virtual_size;
                 procInfo.WorkingSet = (long)temp.ptinfo.pti_resident_size;
index 123821f..f95ed20 100644 (file)
@@ -36,7 +36,7 @@ namespace System.Diagnostics
         /// <param name="processId">The process ID.</param>
         /// <param name="machineName">The machine name.</param>
         /// <returns>The ProcessInfo for the process if it could be found; otherwise, null.</returns>
-        public static ProcessInfo GetProcessInfo(int processId, string machineName)
+        public static ProcessInfo? GetProcessInfo(int processId, string machineName)
         {
             ThrowIfRemoteMachine(machineName);
             return CreateProcessInfo(processId);
index 55432d6..665ecba 100644 (file)
@@ -244,7 +244,7 @@ namespace System.Diagnostics
     internal static class NtProcessInfoHelper
     {
         // Cache a single buffer for use in GetProcessInfos().
-        private static long[] CachedBuffer;
+        private static long[]? CachedBuffer;
 
         // Use a smaller buffer size on debug to ensure we hit the retry path.
 #if DEBUG
@@ -253,7 +253,7 @@ namespace System.Diagnostics
         private const int DefaultCachedBufferSize = 128 * 1024;
 #endif
 
-        internal static ProcessInfo[] GetProcessInfos(Predicate<int> processIdFilter = null)
+        internal static ProcessInfo[] GetProcessInfos(Predicate<int>? processIdFilter = null)
         {
             ProcessInfo[] processInfos;
 
@@ -261,7 +261,7 @@ namespace System.Diagnostics
             int bufferSize = DefaultCachedBufferSize;
 
             // Get the cached buffer.
-            long[] buffer = Interlocked.Exchange(ref CachedBuffer, null);
+            long[]? buffer = Interlocked.Exchange(ref CachedBuffer, null);
 
             try
             {
@@ -343,7 +343,7 @@ namespace System.Diagnostics
             return newSize;
         }
 
-        private static unsafe ProcessInfo[] GetProcessInfos(ReadOnlySpan<byte> data, Predicate<int> processIdFilter)
+        private static unsafe ProcessInfo[] GetProcessInfos(ReadOnlySpan<byte> data, Predicate<int>? processIdFilter)
         {
             // Use a dictionary to avoid duplicate entries if any
             // 60 is a reasonable number for processes on a normal machine.
index 011776d..bd40aea 100644 (file)
@@ -60,7 +60,7 @@ namespace System.Diagnostics
         /// <param name="processId">The process ID.</param>
         /// <param name="machineName">The machine name.</param>
         /// <returns>The ProcessInfo for the process if it could be found; otherwise, null.</returns>
-        public static ProcessInfo GetProcessInfo(int processId, string machineName)
+        public static ProcessInfo? GetProcessInfo(int processId, string machineName)
         {
             if (IsRemoteMachine(machineName))
             {
@@ -150,7 +150,7 @@ namespace System.Diagnostics
                 return;
             }
 
-            SafeTokenHandle tokenHandle = null;
+            SafeTokenHandle? tokenHandle = null;
             try
             {
                 if (!Interop.Advapi32.OpenProcessToken(
@@ -301,7 +301,7 @@ namespace System.Diagnostics
             return GetModules(processId, firstModuleOnly: false);
         }
 
-        public static ProcessModule GetFirstModule(int processId)
+        public static ProcessModule? GetFirstModule(int processId)
         {
             ProcessModuleCollection modules = GetModules(processId, firstModuleOnly: true);
             return modules.Count == 0 ? null : modules[0];
@@ -330,7 +330,7 @@ namespace System.Diagnostics
 
         public static ProcessInfo[] GetProcessInfos(string machineName, bool isRemoteMachine)
         {
-            PerformanceCounterLib library = null;
+            PerformanceCounterLib? library = null;
             try
             {
                 library = PerformanceCounterLib.GetPerformanceCounterLib(machineName, new CultureInfo("en"));
@@ -469,7 +469,7 @@ namespace System.Diagnostics
             for (int i = 0; i < threadInfos.Count; i++)
             {
                 ThreadInfo threadInfo = threadInfos[i];
-                if (processInfos.TryGetValue(threadInfo._processId, out ProcessInfo processInfo))
+                if (processInfos.TryGetValue(threadInfo._processId, out ProcessInfo? processInfo))
                 {
                     processInfo._threadInfoList.Add(threadInfo);
                 }
index f24b5e1..a8723ce 100644 (file)
@@ -13,19 +13,19 @@ namespace System.Diagnostics
     /// </devdoc>
     public class ProcessModule : Component
     {
-        private FileVersionInfo _fileVersionInfo;
+        private FileVersionInfo? _fileVersionInfo;
 
         internal ProcessModule() { }
 
         /// <devdoc>
         ///     Returns the name of the Module.
         /// </devdoc>
-        public string ModuleName { get; internal set; }
+        public string? ModuleName { get; internal set; }
 
         /// <devdoc>
         ///     Returns the full file path for the location of the module.
         /// </devdoc>
-        public string FileName { get; internal set; }
+        public string? FileName { get; internal set; }
 
         /// <devdoc>
         ///     Returns the memory address that the module was loaded at.
@@ -49,7 +49,7 @@ namespace System.Diagnostics
         /// <devdoc>
         ///     Returns version information about the module.
         /// </devdoc>
-        public FileVersionInfo FileVersionInfo => _fileVersionInfo ?? (_fileVersionInfo = FileVersionInfo.GetVersionInfo(FileName));
+        public FileVersionInfo FileVersionInfo => _fileVersionInfo ?? (_fileVersionInfo = FileVersionInfo.GetVersionInfo(FileName!));
 
         public override string ToString() => $"{base.ToString()} ({ModuleName})";
     }
index 6b701ec..f6a8afe 100644 (file)
@@ -31,7 +31,7 @@ namespace System.Diagnostics
 
         internal void RemoveAt(int index) => InnerList.RemoveAt(index);
 
-        public ProcessModule this[int index] => (ProcessModule)InnerList[index];
+        public ProcessModule this[int index] => (ProcessModule)InnerList[index]!;
 
         public int IndexOf(ProcessModule module) => InnerList.IndexOf(module);
 
index 82d3366..98fce7c 100644 (file)
@@ -23,7 +23,7 @@ namespace System.Diagnostics
                     if (key == null)
                         return Array.Empty<string>();
 
-                    string value = key.GetValue(string.Empty) as string;
+                    string? value = key.GetValue(string.Empty) as string;
                     if (string.IsNullOrEmpty(value))
                         return Array.Empty<string>();
 
index 53fd3df..0a52a87 100644 (file)
@@ -8,11 +8,11 @@ namespace System.Diagnostics
 {
     public sealed partial class ProcessStartInfo
     {
-        private string _domain;
+        private string? _domain;
 
         private const bool CaseSensitiveEnvironmentVariables = false;
 
-        public string PasswordInClearText { get; set; }
+        public string? PasswordInClearText { get; set; }
 
         public string Domain
         {
@@ -23,6 +23,6 @@ namespace System.Diagnostics
         public bool LoadUserProfile { get; set; }
 
         [CLSCompliant(false)]
-        public SecureString Password { get; set; }
+        public SecureString? Password { get; set; }
     }
 }
index b6e0f65..b3360d0 100644 (file)
@@ -18,15 +18,15 @@ namespace System.Diagnostics
     /// </devdoc>
     public sealed partial class ProcessStartInfo
     {
-        private string _fileName;
-        private string _arguments;
-        private string _directory;
-        private string _userName;
-        private string _verb;
-        private Collection<string> _argumentList;
+        private string? _fileName;
+        private string? _arguments;
+        private string? _directory;
+        private string? _userName;
+        private string? _verb;
+        private Collection<string>? _argumentList;
         private ProcessWindowStyle _windowStyle;
 
-        internal DictionaryWrapper _environmentVariables;
+        internal DictionaryWrapper? _environmentVariables;
 
         /// <devdoc>
         ///     Default constructor.  At least the <see cref='System.Diagnostics.ProcessStartInfo.FileName'/>
@@ -77,9 +77,9 @@ namespace System.Diagnostics
 
         public bool CreateNoWindow { get; set; }
 
-        public StringDictionary EnvironmentVariables => new StringDictionaryWrapper(Environment as DictionaryWrapper);
+        public StringDictionary EnvironmentVariables => new StringDictionaryWrapper((Environment as DictionaryWrapper)!);
 
-        public IDictionary<string, string> Environment
+        public IDictionary<string, string?> Environment
         {
             get
             {
@@ -88,7 +88,7 @@ namespace System.Diagnostics
                     IDictionary envVars = System.Environment.GetEnvironmentVariables();
 
 #pragma warning disable 0429 // CaseSensitiveEnvironmentVaribles is constant but varies depending on if we build for Unix or Windows
-                    _environmentVariables = new DictionaryWrapper(new Dictionary<string, string>(
+                    _environmentVariables = new DictionaryWrapper(new Dictionary<string, string?>(
                         envVars.Count,
                         CaseSensitiveEnvironmentVariables ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase));
 #pragma warning restore 0429
@@ -99,7 +99,7 @@ namespace System.Diagnostics
                     while (e.MoveNext())
                     {
                         DictionaryEntry entry = e.Entry;
-                        _environmentVariables.Add((string)entry.Key, (string)entry.Value);
+                        _environmentVariables.Add((string)entry.Key, (string?)entry.Value);
                     }
                 }
                 return _environmentVariables;
@@ -110,11 +110,11 @@ namespace System.Diagnostics
         public bool RedirectStandardOutput { get; set; }
         public bool RedirectStandardError { get; set; }
 
-        public Encoding StandardInputEncoding { get; set; }
+        public Encoding? StandardInputEncoding { get; set; }
 
-        public Encoding StandardErrorEncoding { get; set; }
+        public Encoding? StandardErrorEncoding { get; set; }
 
-        public Encoding StandardOutputEncoding { get; set; }
+        public Encoding? StandardOutputEncoding { get; set; }
 
         /// <devdoc>
         ///    <para>
index 8958f95..10c298c 100644 (file)
@@ -32,7 +32,7 @@ namespace System.Diagnostics
         /// </devdoc>
         public ProcessThread this[int index]
         {
-            get { return (ProcessThread)InnerList[index]; }
+            get { return (ProcessThread)InnerList[index]!; }
         }
 
         /// <devdoc>
index 335b1c8..c30b622 100644 (file)
@@ -76,7 +76,7 @@ namespace System.Diagnostics
                 {
                     GC.SuppressFinalize(this);
                     _state.ReleaseRef();
-                    _state = null;
+                    _state = null!;
                 }
             }
         }
@@ -103,7 +103,7 @@ namespace System.Diagnostics
         {
             lock (s_childProcessWaitStates)
             {
-                ProcessWaitState pws;
+                ProcessWaitState? pws;
                 if (isNewChild)
                 {
                     // When the PID is recycled for a new child, we remove the old child.
@@ -159,7 +159,7 @@ namespace System.Diagnostics
         /// </summary>
         internal void ReleaseRef()
         {
-            ProcessWaitState pws;
+            ProcessWaitState? pws;
             Dictionary<int, ProcessWaitState> waitStates = _isChild ? s_childProcessWaitStates : s_processWaitStates;
             lock (waitStates)
             {
@@ -200,7 +200,7 @@ namespace System.Diagnostics
         private readonly bool _usesTerminal;
 
         /// <summary>If a wait operation is in progress, the Task that represents it; otherwise, null.</summary>
-        private Task _waitInProgress;
+        private Task? _waitInProgress;
         /// <summary>The number of alive users of this object.</summary>
         private int _outstandingRefCount;
 
@@ -214,7 +214,7 @@ namespace System.Diagnostics
         /// </summary>
         private DateTime _exitTime;
         /// <summary>A lazily-initialized event set when the process exits.</summary>
-        private ManualResetEvent _exitedEvent;
+        private ManualResetEvent? _exitedEvent;
 
         /// <summary>Initialize the wait state object.</summary>
         /// <param name="processId">The associated process' ID.</param>
@@ -278,7 +278,7 @@ namespace System.Diagnostics
                             // another operation underway, then we'll just tack ours onto the end of it.
                             _waitInProgress = _waitInProgress == null ?
                                 WaitForExitAsync() :
-                                _waitInProgress.ContinueWith((_, state) => ((ProcessWaitState)state).WaitForExitAsync(),
+                                _waitInProgress.ContinueWith((_, state) => ((ProcessWaitState)state!).WaitForExitAsync(),
                                     this, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default).Unwrap();
                         }
                     }
@@ -416,7 +416,7 @@ namespace System.Diagnostics
                 while (true)
                 {
                     bool createdTask = false;
-                    CancellationTokenSource cts = null;
+                    CancellationTokenSource? cts = null;
                     Task waitTask;
 
                     // We're in a polling loop... determine how much time remains
@@ -605,7 +605,7 @@ namespace System.Diagnostics
                     pid = Interop.Sys.WaitIdAnyExitedNoHangNoWait();
                     if (pid > 0)
                     {
-                        if (s_childProcessWaitStates.TryGetValue(pid, out ProcessWaitState pws))
+                        if (s_childProcessWaitStates.TryGetValue(pid, out ProcessWaitState? pws))
                         {
                             // Known Process.
                             if (pws.TryReapChild())
@@ -636,8 +636,8 @@ namespace System.Diagnostics
                 if (checkAll)
                 {
                     // We track things to unref so we don't invalidate our iterator by changing s_childProcessWaitStates.
-                    ProcessWaitState firstToRemove = null;
-                    List<ProcessWaitState> additionalToRemove = null;
+                    ProcessWaitState? firstToRemove = null;
+                    List<ProcessWaitState>? additionalToRemove = null;
                     foreach (KeyValuePair<int, ProcessWaitState> kv in s_childProcessWaitStates)
                     {
                         ProcessWaitState pws = kv.Value;