Skip to content

Commit

Permalink
Nullable annotate System.Diagnostics.Process (dotnet#31671)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
eiriktsarpalis authored Feb 6, 2020
1 parent 1a1a541 commit 90a2d87
Show file tree
Hide file tree
Showing 42 changed files with 282 additions and 258 deletions.
4 changes: 2 additions & 2 deletions src/libraries/Common/src/Interop/FreeBSD/Interop.Process.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ internal static unsafe int[] ListAllPids()
/// 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;
Expand Down Expand Up @@ -359,7 +359,7 @@ public static unsafe ProcessInfo GetProcessInfoById(int pid)
// 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;
Expand Down
28 changes: 15 additions & 13 deletions src/libraries/Common/src/Interop/Linux/cgroups/Interop.cgroups.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -24,14 +26,14 @@ internal enum CGroupVersion { None, CGroup1, CGroup2 };
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))
Expand Down Expand Up @@ -102,9 +104,9 @@ internal static bool TryReadMemoryValueFromFile(string path, out ulong result)

/// <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)
Expand All @@ -126,10 +128,10 @@ private static string FindCGroupMemoryLimitPath()
/// <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.
Expand All @@ -146,20 +148,20 @@ private static string FindCGroupPath(string subsystem, out CGroupVersion version
/// <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))
{
try
{
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"
Expand Down Expand Up @@ -235,20 +237,20 @@ internal static bool TryFindHierarchyMount(string mountInfoFilePath, string subs
/// <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))
{
try
{
using (var reader = new StreamReader(procCGroupFilePath))
{
string line;
string? line;
while ((line = reader.ReadLine()) != null)
{
string[] lineParts = line.Split(':');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -243,7 +245,7 @@ internal static bool TryReadStatusFile(int pid, out ParsedStatus result, Reusabl

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.
Expand Down Expand Up @@ -312,7 +314,7 @@ internal static bool TryParseStatFile(string statFilePath, out ParsedStat result

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.
Expand Down Expand Up @@ -415,7 +417,7 @@ internal static bool TryParseStatusFile(string statusFilePath, out ParsedStatus
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
{
Expand Down
4 changes: 3 additions & 1 deletion src/libraries/Common/src/Interop/OSX/Interop.libproc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -362,7 +364,7 @@ private static extern unsafe int proc_pidinfo(

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -43,7 +45,7 @@ internal static unsafe int ForkAndExecProcess(

[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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
// 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;

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -16,7 +18,7 @@ internal static extern bool CreateProcessWithLogonW(
string domain,
IntPtr password,
LogonFlags logonFlags,
string appName,
string? appName,
[In] StringBuilder cmdLine,
int creationFlags,
IntPtr environmentBlock,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -13,7 +15,7 @@ internal partial class Kernel32
{
[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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -14,7 +15,7 @@ internal sealed class ProcessWaitHandle : WaitHandle
{
internal ProcessWaitHandle(SafeProcessHandle processHandle)
{
SafeWaitHandle waitHandle = null;
SafeWaitHandle? waitHandle;
SafeProcessHandle currentProcHandle = Interop.Kernel32.GetCurrentProcess();
bool succeeded = Interop.Kernel32.DuplicateHandle(
currentProcHandle,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/libraries/Common/src/System/Text/ReusableTextReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -21,7 +23,7 @@ internal sealed class ReusableTextReader
/// <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)
{
Expand Down
Loading

0 comments on commit 90a2d87

Please sign in to comment.