From e5abbd43401e7252185b46ab68e7ee6df7f0fdc7 Mon Sep 17 00:00:00 2001 From: Tim Cassell Date: Sun, 26 Oct 2025 19:54:41 -0400 Subject: [PATCH] Add MacOS support to `DataTarget.CreateSnapshotAndAttach` --- .../DataReaders/MacOS/MacOSSnapshotTarget.cs | 63 +++++++++++++++++++ .../DataTarget.cs | 5 ++ 2 files changed, 68 insertions(+) create mode 100644 src/Microsoft.Diagnostics.Runtime/DataReaders/MacOS/MacOSSnapshotTarget.cs diff --git a/src/Microsoft.Diagnostics.Runtime/DataReaders/MacOS/MacOSSnapshotTarget.cs b/src/Microsoft.Diagnostics.Runtime/DataReaders/MacOS/MacOSSnapshotTarget.cs new file mode 100644 index 000000000..c98da3eb3 --- /dev/null +++ b/src/Microsoft.Diagnostics.Runtime/DataReaders/MacOS/MacOSSnapshotTarget.cs @@ -0,0 +1,63 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.IO; +using Microsoft.Diagnostics.NETCore.Client; +using Microsoft.Diagnostics.Runtime.MacOS; + +namespace Microsoft.Diagnostics.Runtime +{ + internal sealed class MacOSSnapshotTarget : CustomDataTarget + { + private readonly int _pid; + private readonly string _filename; + + private MacOSSnapshotTarget(IDataReader reader, int pid, string filename) : base(reader, null) + { + _pid = pid; + _filename = filename; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + try + { + File.Delete(_filename); + } + catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or ArgumentException or NotSupportedException) + { + } + } + + public override string ToString() => $"{_filename} (snapshot of pid:{_pid:x})"; + + public static MacOSSnapshotTarget CreateSnapshotFromProcess(int pid) + { + string? dumpPath = Path.GetTempFileName(); + try + { + try + { + DiagnosticsClient client = new(pid); + client.WriteDump(DumpType.Full, dumpPath, logDumpGeneration: false); + } + catch (ServerErrorException sxe) + { + throw new ArgumentException($"Unable to create a snapshot of process {pid:x}.", sxe); + } + + MacOSSnapshotTarget result = new(new MachOCoreReader(dumpPath, File.OpenRead(dumpPath), leaveOpen: false), pid, dumpPath); + dumpPath = null; + return result; + } + finally + { + if (dumpPath != null) + File.Delete(dumpPath); + } + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Diagnostics.Runtime/DataTarget.cs b/src/Microsoft.Diagnostics.Runtime/DataTarget.cs index f8096a7ad..24e880750 100644 --- a/src/Microsoft.Diagnostics.Runtime/DataTarget.cs +++ b/src/Microsoft.Diagnostics.Runtime/DataTarget.cs @@ -440,6 +440,11 @@ public static DataTarget CreateSnapshotAndAttach(int processId, TokenCredential? return new DataTarget(LinuxSnapshotTarget.CreateSnapshotFromProcess(processId)); } + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return new DataTarget(MacOSSnapshotTarget.CreateSnapshotFromProcess(processId)); + } + throw GetPlatformException(); }