Skip to content

Commit 5c564be

Browse files
committed
SunOS process and thread support (native)
Read binary psinfo for System.Diagnostic.Process on SunOS Alternate approach using src/native/libs/System.Native Add native/libs/System.Native/pal_io.c etc. Add src/libraries/Common/src/Interop/SunOS/procfs Add src/libraries/System.Diagnostics.Process Thanks for initial prototype help from: Austin Wise <[email protected]>
1 parent d7f655d commit 5c564be

File tree

17 files changed

+838
-58
lines changed

17 files changed

+838
-58
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
internal static partial class Interop
8+
{
9+
internal static partial class @procfs
10+
{
11+
internal const string RootPath = "/proc/";
12+
private const string psinfoFileName = "/psinfo";
13+
private const string lwpDirName = "/lwp";
14+
private const string lwpsinfoFileName = "/lwpsinfo";
15+
16+
// Constants from sys/procfs.h
17+
private const int PRARGSZ = 80;
18+
19+
// Output type for TryGetProcessInfoById()
20+
// Keep in sync with pal_io.h ProcessStatus
21+
[StructLayout(LayoutKind.Sequential)]
22+
internal struct ProcessInfo
23+
{
24+
internal ulong VirtualSize;
25+
internal ulong ResidentSetSize;
26+
internal Interop.Sys.TimeSpec StartTime;
27+
internal Interop.Sys.TimeSpec CpuTotalTime; // user+sys
28+
internal int Pid;
29+
internal int ParentPid;
30+
internal int SessionId;
31+
internal int Priority;
32+
internal int NiceVal;
33+
// add more fields when needed.
34+
}
35+
36+
// Output type for TryGetThreadInfoById()
37+
// Keep in sync with pal_io.h ThreadStatus
38+
[StructLayout(LayoutKind.Sequential)]
39+
internal struct ThreadInfo
40+
{
41+
internal Interop.Sys.TimeSpec StartTime;
42+
internal Interop.Sys.TimeSpec CpuTotalTime; // user+sys
43+
internal int Tid;
44+
internal int Priority;
45+
internal int NiceVal;
46+
internal char StatusCode;
47+
// add more fields when needed.
48+
}
49+
50+
internal static string GetInfoFilePathForProcess(int pid) =>
51+
$"{RootPath}{(uint)pid}{psinfoFileName}";
52+
53+
internal static string GetLwpDirForProcess(int pid) =>
54+
$"{RootPath}{(uint)pid}{lwpDirName}";
55+
56+
internal static string GetInfoFilePathForThread(int pid, int tid) =>
57+
$"{RootPath}{(uint)pid}{lwpDirName}/{(uint)tid}{lwpsinfoFileName}";
58+
59+
}
60+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.IO;
7+
using System.Runtime.CompilerServices;
8+
using System.Runtime.InteropServices;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class @procfs
13+
{
14+
15+
// See caller: ProcessManager.SunOS.cs
16+
17+
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadProcessStatusInfo", SetLastError = true)]
18+
private static unsafe partial int ReadProcessStatusInfo(int pid, ProcessInfo* processInfo, byte* argBuf, int argBufSize);
19+
20+
// Handy helpers for Environment.SunOS etc.
21+
22+
/// <summary>
23+
/// Attempts to get status info for the specified process ID.
24+
/// </summary>
25+
/// <param name="pid">PID of the process to read status info for.</param>
26+
/// <param name="processInfo">The pointer to ProcessInfo instance.</param>
27+
/// <returns>
28+
/// true if the process status was read; otherwise, false.
29+
/// </returns>
30+
internal static unsafe bool TryGetProcessInfoById(int pid, out ProcessInfo processInfo)
31+
{
32+
ProcessInfo info = default;
33+
if (ReadProcessStatusInfo(pid, &info, null, 0) < 0)
34+
{
35+
Interop.ErrorInfo errorInfo = Sys.GetLastErrorInfo();
36+
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
37+
}
38+
processInfo = info;
39+
40+
return true;
41+
}
42+
43+
// Variant that also gets the arg string.
44+
internal static unsafe bool TryGetProcessInfoById(int pid, out ProcessInfo processInfo, out string argString)
45+
{
46+
ProcessInfo info = default;
47+
byte* argBuf = stackalloc byte[PRARGSZ];
48+
if (ReadProcessStatusInfo(pid, &info, argBuf, PRARGSZ) < 0)
49+
{
50+
Interop.ErrorInfo errorInfo = Sys.GetLastErrorInfo();
51+
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
52+
}
53+
processInfo = info;
54+
argString = Marshal.PtrToStringUTF8((IntPtr)argBuf)!;
55+
56+
return true;
57+
}
58+
59+
60+
}
61+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.IO;
7+
using System.Runtime.CompilerServices;
8+
using System.Runtime.InteropServices;
9+
10+
internal static partial class Interop
11+
{
12+
internal static partial class @procfs
13+
{
14+
15+
// See caller: ProcessManager.SunOS.cs
16+
17+
[LibraryImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadProcessLwpInfo", SetLastError = true)]
18+
internal static unsafe partial int ReadProcessLwpInfo(int pid, int tid, ThreadInfo* threadInfo);
19+
20+
/// <summary>
21+
/// Attempts to get status info for the specified thread ID.
22+
/// </summary>
23+
/// <param name="pid">PID of the process to read status info for.</param>
24+
/// <param name="tid">TID of the thread to read status info for.</param>
25+
/// <param name="threadInfo">The pointer to ThreadInfo instance.</param>
26+
/// <returns>
27+
/// true if the process status was read; otherwise, false.
28+
/// </returns>
29+
internal static unsafe bool TryGetThreadInfoById(int pid, int tid, out ThreadInfo threadInfo)
30+
{
31+
ThreadInfo info = default;
32+
if (ReadProcessLwpInfo(pid, tid, &info) < 0)
33+
{
34+
Interop.ErrorInfo errorInfo = Sys.GetLastErrorInfo();
35+
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
36+
}
37+
threadInfo = info;
38+
39+
return true;
40+
}
41+
42+
}
43+
}

src/libraries/Common/src/Interop/SunOS/procfs/Interop.ProcFsStat.TryReadProcessStatusInfo.cs

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.InteropServices;
6+
7+
internal static partial class Interop
8+
{
9+
internal static partial class Sys
10+
{
11+
internal struct TimeSpec
12+
{
13+
internal long TvSec;
14+
internal long TvNsec;
15+
}
16+
}
17+
}

src/libraries/Common/src/Interop/Unix/System.Native/Interop.UTimensat.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ internal static partial class Interop
88
{
99
internal static partial class Sys
1010
{
11-
internal struct TimeSpec
12-
{
13-
internal long TvSec;
14-
internal long TvNsec;
15-
}
16-
1711
/// <summary>
1812
/// Sets the last access and last modified time of a file
1913
/// </summary>

src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ public static partial class PlatformDetection
4747
public static bool IsNotMacCatalyst => !IsMacCatalyst;
4848
public static bool Isillumos => RuntimeInformation.IsOSPlatform(OSPlatform.Create("ILLUMOS"));
4949
public static bool IsSolaris => RuntimeInformation.IsOSPlatform(OSPlatform.Create("SOLARIS"));
50+
public static bool IsSunOS => Isillumos || IsSolaris;
5051
public static bool IsBrowser => RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER"));
5152
public static bool IsWasi => RuntimeInformation.IsOSPlatform(OSPlatform.Create("WASI"));
5253
public static bool IsNotBrowser => !IsBrowser;

src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-maccatalyst;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)</TargetFrameworks>
4+
<TargetFrameworks>$(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-freebsd;$(NetCoreAppCurrent)-linux;$(NetCoreAppCurrent)-osx;$(NetCoreAppCurrent)-maccatalyst;$(NetCoreAppCurrent)-ios;$(NetCoreAppCurrent)-tvos;$(NetCoreAppCurrent)-illumos;$(NetCoreAppCurrent)-solaris;$(NetCoreAppCurrent)</TargetFrameworks>
55
<DefineConstants>$(DefineConstants);FEATURE_REGISTRY</DefineConstants>
66
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
77
<UseCompilerGeneratedDocXmlFile>false</UseCompilerGeneratedDocXmlFile>
@@ -369,6 +369,21 @@
369369
Link="Common\Interop\FreeBSD\Interop.Process.GetProcInfo.cs" />
370370
</ItemGroup>
371371

372+
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'illumos' or '$(TargetPlatformIdentifier)' == 'solaris'">
373+
<Compile Include="System\Diagnostics\Process.BSD.cs" />
374+
<Compile Include="System\Diagnostics\Process.SunOS.cs" />
375+
<Compile Include="System\Diagnostics\ProcessManager.SunOS.cs" />
376+
<Compile Include="System\Diagnostics\ProcessThread.SunOS.cs" />
377+
<Compile Include="$(CommonPath)Interop\Unix\System.Native\Interop.TimeSpec.cs"
378+
Link="Common\Interop\Unix\System.Native\Interop.TimeSpec.cs" />
379+
<Compile Include="$(CommonPath)Interop\SunOS\procfs\Interop.ProcFs.Definitions.cs"
380+
Link="Common\Interop\SunOS\procfs\Interop.ProcFs.Definitions.cs" />
381+
<Compile Include="$(CommonPath)Interop\SunOS\procfs\Interop.ProcFs.TryGetProcessInfoById.cs"
382+
Link="Common\Interop\SunOS\procfs\Interop.ProcFs.TryGetProcessInfoById.cs" />
383+
<Compile Include="$(CommonPath)Interop\SunOS\procfs\Interop.ProcFs.TryGetThreadInfoById.cs"
384+
Link="Common\Interop\SunOS\procfs\Interop.ProcFs.TryGetThreadInfoById.cs" />
385+
</ItemGroup>
386+
372387
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'ios' or '$(TargetPlatformIdentifier)' == 'tvos'">
373388
<Compile Include="System\Diagnostics\Process.iOS.cs" />
374389
<Compile Include="System\Diagnostics\ProcessManager.iOS.cs" />

0 commit comments

Comments
 (0)