Skip to content

Conversation

gwr
Copy link
Contributor

@gwr gwr commented Jul 24, 2024

Read binary psinfo for System.Diagnostic.Process on SunOS (Solaris or illumos).
No failures in System.Diagnostic.Process.Tests (but lots of skip)

BTW, I tried rebasing on main from Mon. this week and ran into problems downloading stuff.
Not sure why, but it didn't seem to have anything to do with my changes.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jul 24, 2024
@am11
Copy link
Member

am11 commented Jul 24, 2024

Lets drop the changes which are already submitted in other PRs.

@am11
Copy link
Member

am11 commented Jul 24, 2024

Good start! I've left initial feedback, which I anticipate the maintainers will point out. :)

@am11 am11 added the os-SunOS SunOS, currently not officially supported label Jul 24, 2024
@gwr
Copy link
Contributor Author

gwr commented Jul 24, 2024

Good start! I've left initial feedback, which I anticipate the maintainers will point out. :)

Thanks. I had not yet seen #105207 when I opened this. I think @AustinWise and I should figure out how to get the prerequisite fixes shown there (and here) all integrated, and then I'll rebase the last parts of this onto that.

@gwr
Copy link
Contributor Author

gwr commented Jul 24, 2024

Lets drop the changes which are already submitted in other PRs.

I'd love to, but I do not see a way to do "stacked" PRs, where one PR targets the branch of another PR.
If I drop the prerequisite changes then things break. Suggestions welcome.

@am11
Copy link
Member

am11 commented Jul 24, 2024

Create a local branch feature/illumos-port with all the miscellaneous changes. Then keep this branch only for System.Diagnostics.Port changes. You can git cherry-pick <spaces-separated commit hashes> across the branches.

@risc-vv
Copy link

risc-vv commented Jul 10, 2025

RISC-V Release-CLR-QEMU: 9082 / 9112 (99.67%)
=======================
      passed: 9082
      failed: 2
     skipped: 597
      killed: 28
------------------------
 TOTAL tests: 9709
VIRTUAL time: 37h 26min 40s 438ms
   REAL time: 38min 9s 841ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V Release-CLR-VF2: 9083 / 9113 (99.67%)
=======================
      passed: 9083
      failed: 2
     skipped: 597
      killed: 28
------------------------
 TOTAL tests: 9710
VIRTUAL time: 11h 43min 10s 548ms
   REAL time: 47min 22s 50ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V Release-FX-QEMU: 278604 / 279696 (99.61%)
=======================
      passed: 278604
      failed: 1083
     skipped: 39
      killed: 9
------------------------
 TOTAL tests: 279735
VIRTUAL time: 29h 11min 36s 714ms
   REAL time: 1h 11min 4s 97ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

RISC-V Release-FX-VF2: 309598 / 311334 (99.44%)
=======================
      passed: 309598
      failed: 1729
     skipped: 39
      killed: 7
------------------------
 TOTAL tests: 311373
VIRTUAL time: 21h 13min 12s 292ms
   REAL time: 2h 17min 0s 803ms
=======================

report.xml, report.md, failures.xml, testclr_details.tar.zst

Build information and commands

GIT: 3a905a16032b7a90d59d66c343b51123cb3e9f29
CI: d6c9c1ab3a7411819463edc05ded301e89ba586a
REPO: dotnet/runtime
BRANCH: main
CONFIG: Release
LIB_CONFIG: Release

jkotas pushed a commit that referenced this pull request Jul 13, 2025
* Fix illumos compile error at minipal/debugger.c:127

  dotnet/runtime/src/native/minipal/debugger.c:127:5: error: implicit declaration of function 'snprintf' [-Werror=implicit-function-declaration]
    127 |     snprintf(statusFilename, sizeof(statusFilename), "/proc/%d/status", getpid());
        |     ^~~~~~~~

* Fix illumos compile error in minipal/thread.h

  src/native/minipal/thread.h:73:23: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
     73 |         tid = (size_t)(void*)pthread_self();
        |                       ^~~~~~~~~~~~~~~~~~~~~

* Fix illumos compile error in native/libs/System.Native/pal_mount.c

 src/native/libs/System.Native/pal_mount.c:164:38: error: 'struct statvfs' has no member named 'f_type'
    164 |         *formatType = (int64_t)(stats.f_type);
        |                                      ^

* Fix illumos compile error in coreclr/pal/src/thread/thread.cpp

  /home/gwr/dotnet/runtime/src/coreclr/pal/src/thread/thread.cpp:1367:5: error: 'cid' was not declared in this scope
   1367 |     cid = CLOCK_THREAD_CPUTIME_ID;
        |     ^~~
@gwr
Copy link
Contributor Author

gwr commented Jul 14, 2025

I'm still not sure how to get the System.Diagnostics.Process/test stuff onto my test host and run it. I've tried to follow the workflow documents but those don't say much about cross builds like I have to do. Cook-book commands would be a great help. Thx!

@am11
Copy link
Member

am11 commented Jul 14, 2025

There is no easy way to run libraries tests when we are in the middle of porting shared framework (itself) and sdk/msbuild aren't fully functional on the platform. The improvised way involves gathering references and assemblies then feed it to dotnet(1) same as how the test command line gets serialized on linux. If you are unfamiliar with sdk/msbuild commands, it complicates things further.

@gwr
Copy link
Contributor Author

gwr commented Jul 14, 2025

OK, so I'm trying to become more familiar, and have tried looking at how this works on linux.
I can copy over simple DLLs and run them (eg. HelloWorld, and my procinfo test).
My current obstacle is that the xunit.console.dll is no longer there (how I used to run tests).
The docs say to use "dotnet test", but that's not there yet and I'm not sure what to cross build and how to copy it into place to make that work so I can run the S.D.Process tests again.

I'm building like this:

export CMAKE_MAKE_PROGRAM=/usr/local/bin/cmake
export ROOTFS_DIR=/crossrootfs/x64
./build.sh clr+libs+libs.tests -c Debug -cross -os illumos -gcc --bootstrap

and then copying this over to the illumos test system and unpack:

artifacts/packages/Debug/Shipping/dotnet-runtime-10.0.0-dev-illumos-x64.tar.gz

That much gives me a working dotnet command, but I don't see any SDK stuff.
I could use help getting the SDK built and copied over. I don't see that case covered in the workflow docs. I only see instructions for native build.

@am11
Copy link
Member

am11 commented Jul 14, 2025

I think your test program from #34944 (comment) is sufficient for now. Just add process spawn case and if that works, we are good to go for this initial iteration.

New platform (especially new operating system as opposed to new arch) isn't a smooth sail and engineering doesn't pay too much attention to it during larger refactoring (mainly because it's once in a lifetime thing for a given platform). Once, System.Diagnostics.Process and the remaining two libs are ported, we can get a full blown SDK though source-build. Then it'd be a matter of extracting that SDK at root of the repo cloned in illumos based OS and running $repo_root/dotnet.sh build -t:Test <path to test project dir>. With that, faster iterations by running various test suites, finding out issues and resolving them would be seamless.

@am11
Copy link
Member

am11 commented Jul 14, 2025

@gwr has confirmed that ad-hoc tests are passing. Full lib tests will be run once we get the bootstrapped SDK ready (which is getting closer). So this looks good. 👍

@janvorli, @jkotas, this is ready for review. PTAL.

@gwr
Copy link
Contributor Author

gwr commented Jul 25, 2025

Any more feedback? Thanks. (bump?)

@jeffhandley jeffhandley requested a review from jkotas September 1, 2025 21:28

<!-- The following RIDs are not officically supported and are not
built during official builds, however we wish to include them
in our runtime.json to enable others to provide them. -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the runtime.json that this talks about going to show up?

I am wondering whether this is still needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the runtime.json that this talks about going to show up?

<!-- Include Unofficial Build RIDs in runtime.json's but do not include in the platform manifest -->
<BuildRID Include="@(UnofficialBuildRID)" Exclude="@(_buildingOnRID)">
<ExcludeFromPlatformManifest>true</ExcludeFromPlatformManifest>
</BuildRID>
<BuildRID Include="@(_buildingOnRID)"/>
<RestoreBuildRID Include="@(BuildRID)" Exclude="@(UnofficialBuildRID)" />

Copy link
Member

@jkotas jkotas Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does BuildRID flow to runtime.json? What's the path to the runtime.json file? Is it shipping anywhere?

I think it would be best to separate the infra changes from the System.Diagnostics.Process changes. PRs that combine multiple completely unrelated fixes are hard to land.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, this code is here for ages. PR isn't inventing anything new.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know it has been there for ages. I am trying to understand what it is still used for and whether it is still needed. I am not able to able to find runtime.json that the comment talks about.

@gwr
Copy link
Contributor Author

gwr commented Sep 7, 2025

After the recent merge of main into the PR branch, I'm getting a build error I don't understand:


$ export CMAKE_MAKE_PROGRAM=/usr/local/bin/cmake
$ export ROOTFS_DIR=/crossrootfs/x64
$ ./build.sh clr+libs+libs.tests -c Debug -cross -os illumos -gcc --bootstrap
... 
  [ 50%] Building CXX object vm/CMakeFiles/cee_dac.dir/readytorunstandalonemethodmetadata.cpp.o
  /home/gwr/dotnet/runtime/src/coreclr/vm/methodtable.cpp: In static member function 'static MethodTable::MethodData* MethodTable::GetMethodDataHelper(MethodTable*, MethodTable*, MethodDataComputeOptions)':
  /home/gwr/dotnet/runtime/src/coreclr/vm/methodtable.cpp:7130:52: error: 'static void MethodTable::MethodData::operator delete(void*)' called on pointer returned from a mismatched allocation function [-Werror=mismatched-new-delete]
   7130 |             pData = new MethodDataInterface(pMTDecl);
        |                                                    ^
  /home/gwr/dotnet/runtime/src/coreclr/vm/methodtable.cpp:7130:52: note: returned from 'void* operator new(std::size_t)'
   7130 |             pData = new MethodDataInterface(pMTDecl);
        |                                                    ^
  [ 50%] Building CXX object vm/wks/CMakeFiles/cee_wks_core.dir/__/onstackreplacement.cpp.o
  cc1plus: all warnings being treated as errors
  make[3]: *** [vm/wks/CMakeFiles/cee_wks_core.dir/build.make:973: vm/wks/CMakeFiles/cee_wks_core.dir/__/methodtable.cpp.o] Error 1
  make[3]: *** Waiting for unfinished jobs....
...
  [ 52%] Linking CXX static library libcee_dac.a
  [ 52%] Built target cee_dac
  make[1]: *** [CMakeFiles/Makefile2:1944: CMakeFiles/runtime.dir/rule] Error 2
  make: *** [Makefile:228: runtime] Error 2
  ~/dotnet/runtime/src/coreclr
  Failed to build "CoreCLR component".
/home/gwr/dotnet/runtime/src/coreclr/runtime.proj(116,5): error MSB3073: The command ""/home/gwr/dotnet/runtime/src/coreclr/build-runtime.sh" -x64 -debug gcc -cross -os illumos -targetrid illumos-x64 -cmakeargs "-DCLR_DOTNET_RID=illumos-x64" -cmakeargs "-DCLR_DOTNET_HOST_PATH=/home/gwr/dotnet/runtime/.dotnet/dotnet" -cmakeargs "-DCDAC_BUILD_TOOL_BINARY_PATH=/home/gwr/dotnet/runtime/artifacts/bin/coreclr/illumos.x64.Debug/cdac-build-tool/cdac-build-tool.dll" -component runtime" exited with code 2.

Build FAILED.

Help? (resolved below. See #119447)

@jkotas
Copy link
Member

jkotas commented Sep 7, 2025

error: 'static void MethodTable::MethodData::operator delete(void*)' called on pointer returned from a mismatched allocation function

Looks related to #119112

@gwr
Copy link
Contributor Author

gwr commented Sep 7, 2025

Looks related to #119112

Thanks. I picked up changes through Aug 30 (including that fix) but I'm still getting the error. That business with destructors is a bit tricky for me to figure out.

@gwr
Copy link
Contributor Author

gwr commented Sep 7, 2025

Looks related to #119112

This seems to let it build. Does this look right?

diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp
index 6389c40c855..167f2a614c5 100644
--- a/src/coreclr/vm/methodtable.cpp
+++ b/src/coreclr/vm/methodtable.cpp
@@ -7127,7 +7127,7 @@ MethodTable::MethodData *MethodTable::GetMethodDataHelper(MethodTable *pMTDecl,
     // If we get here, there are no entries in the cache.
     if (pMTDecl == pMTImpl) {
         if (pMTDecl->IsInterface()) {
-            pData = new MethodDataInterface(pMTDecl);
+            pData = new ({pMTDecl}) MethodDataInterface(pMTDecl);
         }
         else {
             MethodDataHolder h(FindParentMethodDataHelper(pMTDecl));

I went ahead and created a PR with this: #119447

@gwr
Copy link
Contributor Author

gwr commented Sep 9, 2025

I'm catching up with the merge first, and then updating as requested in reviews.

@gwr
Copy link
Contributor Author

gwr commented Sep 9, 2025

Base now on main as of Aug 30. to pick up #119112

Read /proc (binary) psinfo for System.Diagnostic.Process
using src/native/libs/System.Native C functions.

Add native/libs/System.Native/pal_io.c etc.
Add src/libraries/Common/src/Interop/SunOS/procfs
Add src/libraries/System.Diagnostics.Process

Co-authored-by: Austin Wise <AustinWise@gmail.com>
Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com>
@gwr
Copy link
Contributor Author

gwr commented Sep 9, 2025

Pushed new version with changes requested by reviewers,
and drop commits that will be in other PRs.

Note that to build this, three other changes are requied:

In case anyone wants to build this, here's a branch with all four changes:
https://github.com/gwr/dotnet-runtime/commits/illumos6

internal int Tid;
internal int Priority;
internal int NiceVal;
internal char StatusCode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is uint8_t in the unmanaged view. It should be byte here.

(char is 16-bit in C#, so there is a mismatch between the managed and unmanaged definitions.)

Comment on lines +377 to +378
<Compile Include="$(CommonPath)Interop\SunOS\procfs\Interop.ProcFs.Definitions.cs"
Link="Common\Interop\SunOS\procfs\Interop.ProcFs.Definitions.cs" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Compile Include="$(CommonPath)Interop\SunOS\procfs\Interop.ProcFs.Definitions.cs"
Link="Common\Interop\SunOS\procfs\Interop.ProcFs.Definitions.cs" />
<Compile Include="$(CommonPath)Interop\SunOS\procfs\Interop.ProcFs.cs"
Link="Common\Interop\SunOS\procfs\Interop.ProcFs.cs" />

Nit: There is no other *.Definitions.cs file under libraries. To follow the repo conventions, this should be Interop.ProcFs.cs or Interop.ProcFs.Common.cs - if there is anything left in this file after incorporating the other feedback.

// Output type for TryGetProcessInfoById()
// Keep in sync with pal_io.h ProcessInfo
[StructLayout(LayoutKind.Sequential)]
internal struct ProcessInfo
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make more sense for this to be in Interop.ProcFs.TryGetProcessInfoById.cs. We typically place the structures that support the internal API in the same file as the API, so that one can include the least amount of interop goo a lot of unnecessary goo to use the internal API.

internal char StatusCode;
}

internal static string GetInfoFilePathForProcess(int pid) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks unused

internal static string GetLwpDirForProcess(int pid) =>
$"{RootPath}{(uint)pid}{lwpDirName}";

internal static string GetInfoFilePathForThread(int pid, int tid) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks unused

}
return iinfo;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Comment on lines +129 to +130
Interop.procfs.ProcessInfo iinfo;
if (!Interop.procfs.TryGetProcessInfoById(_processId, out iinfo))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Interop.procfs.ProcessInfo iinfo;
if (!Interop.procfs.TryGetProcessInfoById(_processId, out iinfo))
Interop.procfs.ProcessInfo processInfo;
if (!Interop.procfs.TryGetProcessInfoById(_processId, out processInfo))

Does the i prefix in iinfo mean something?

{
public partial class Process : IDisposable
{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

/// <param name="pid">PID of the process to read status info for.</param>
/// <param name="processInfo">The pointer to ProcessInfo instance.</param>
/// <returns>
/// true if the process status was read; otherwise, false.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method implementation throws on errors. It never returns false. Should it be void GetProcessInfoById instead? (dtto for other similar Try methods)

Comment on lines +32 to +38
ProcessInfo info = default;
if (ReadProcessInfo(pid, &info, null, 0) < 0)
{
Interop.ErrorInfo errorInfo = Sys.GetLastErrorInfo();
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
}
processInfo = info;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ProcessInfo info = default;
if (ReadProcessInfo(pid, &info, null, 0) < 0)
{
Interop.ErrorInfo errorInfo = Sys.GetLastErrorInfo();
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
}
processInfo = info;
fixed (ProcessInfo* pProcessInfo = &processInfo)
{
if (ReadProcessInfo(pid, pProcessInfo, null, 0) < 0)
{
Interop.ErrorInfo errorInfo = Sys.GetLastErrorInfo();
throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
}
}

ProcessInfo is a structure with non-trivial size. It would be better to pin it to avoid unnecessary copying. (dtto for other similar places)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Diagnostics.Process community-contribution Indicates that the PR has been added by a community member os-SunOS SunOS, currently not officially supported port
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants