Skip to content

Comments

[DiagnosticsClient] Add cross-container support#5735

Open
mdh1418 wants to merge 3 commits intodotnet:mainfrom
mdh1418:cross-namespace-ipc
Open

[DiagnosticsClient] Add cross-container support#5735
mdh1418 wants to merge 3 commits intodotnet:mainfrom
mdh1418:cross-namespace-ipc

Conversation

@mdh1418
Copy link
Member

@mdh1418 mdh1418 commented Feb 20, 2026

Summary

When diagnostic tools (dotnet-trace, dotnet-counters, dotnet-stack, dotnet-dump) run in a sidecar container with pid: host, they cannot find the target process's diagnostic IPC socket. The socket is named using the container-internal PID (NSpid) and located under /proc/{hostPid}/root/{tmpdir}/, but the tools only look in local /tmp/.

This PR adds cross-namespace IPC resolution to Microsoft.Diagnostics.NETCore.Client so all diagnostic tools work transparently across PID namespaces.

Fixes #5694

Changes

Commit 1: Core IPC transport support

  • Add TryGetNamespacePid() — reads /proc/{pid}/status NSpid to detect cross-namespace processes
  • Add GetProcessTmpDir() — reads /proc/{pid}/environ for TMPDIR
  • Merge TryGetDefaultAddress into parameterized TryResolveAddress() — handles both Windows named pipes and Unix sockets from any base path
  • Simplify GetDefaultAddress() flow: try cross-namespace → try local → error with platform-specific guidance
  • All Linux-specific methods self-guard, returning safe defaults on other platforms

Commit 2: Cross-namespace process enumeration

  • Add GetCrossNamespacePublishedProcesses() — scans /proc for processes in different namespaces with diagnostic sockets
  • Refactor GetLocalPublishedProcesses() to be self-contained (handles its own file listing and exceptions)
  • GetPublishedProcesses() is now a clean symmetric union of both methods
  • Introduce ProcPath and GetDiagnosticSocketSearchPattern() constants to avoid hardcoding

Commit 3: Unit tests

  • Extract TryParseNamespacePid() and ParseTmpDir() for testable parsing logic
  • 11 parsing tests with synthetic data (NSpid variants, TMPDIR, socket patterns)
  • 4 behavioral tests with [ConditionalFact] (same-namespace detection, child process TMPDIR reading, platform guards, error paths)

How it works

GetDefaultAddress(pid):
  1. TryGetNamespacePid(pid) → reads /proc/{pid}/status NSpid
     If cross-namespace: TryResolveAddress(/proc/{pid}/root/{tmpdir}/, nsPid)
  2. TryResolveAddress(IpcRootPath, pid) → local socket/named pipe lookup
  3. Error with platform-specific guidance

No explicit platform branching in GetDefaultAddress — platform logic is inside TryResolveAddress and the self-guarding helper methods.

Cross-Namespace IPC Test Results

Setup

Docker Compose with two containers:

  • target-app: .NET 10.0-preview app running with PID 1 inside its container (host PID 2209)
  • tracer: .NET 10.0 SDK container with privileged: true and pid: host
$ cat /proc/2209/status | grep NSpid
NSpid:  2209    1

$ ls /proc/2209/root/tmp/dotnet-diagnostic-*
/proc/2209/root/tmp/dotnet-diagnostic-1-32221497-socket

$ ls /tmp/dotnet-diagnostic-*
ls: cannot access '/tmp/dotnet-diagnostic-*': No such file or directory

The target app's IPC socket is named with its container-internal PID (1) and is only accessible via /proc/2209/root/tmp/ from the tracer's namespace. No socket exists in the tracer's local /tmp/.

Baseline: Stock Tools v9.0.661903 (Before Fix)

All tools fail — ps finds no processes, all connection attempts throw ServerNotAvailableException.

# Tool Command Result
B1 dotnet-trace ps No supported .NET processes were found
B2 dotnet-counters ps No supported .NET processes were found
B3 dotnet-trace collect -p 2209 ServerNotAvailableException: Unable to connect to Process 2209
B4 dotnet-trace collect-linux --probe -p 2209 ServerNotAvailableException: Unable to connect to Process 2209
B5 dotnet-trace collect-linux -p 2209 ServerNotAvailableException: Unable to connect to Process 2209
B6 dotnet-counters monitor -p 2209 ServerNotAvailableException: Unable to connect to Process 2209
B7 dotnet-stack report -p 2209 ServerNotAvailableException: Unable to connect to Process 2209
B8 dotnet-dump collect -p 2209 Unable to connect to Process 2209
Full baseline output
--- TEST B1: dotnet-trace ps ---
No supported .NET processes were found

--- TEST B2: dotnet-counters ps ---
No supported .NET processes were found

--- TEST B3: dotnet-trace collect -p 2209 ---
[ERROR] Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException:
Unable to connect to Process 2209. Please verify that /tmp/ is writable by the current user.
   at PidIpcEndpoint.GetDefaultAddress(Int32 pid) in IpcTransport.cs:line 367
   at CollectCommandHandler.Collect(...) in CollectCommand.cs:line 262

--- TEST B4: dotnet-trace collect-linux --probe -p 2209 ---
Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException:
Unable to connect to Process 2209. ...
   at PidIpcEndpoint.GetDefaultAddress(Int32 pid) in IpcTransport.cs:line 367
   at CollectLinuxCommandHandler.SupportsCollectLinux(...) in CollectLinuxCommand.cs:line 207

--- TEST B5: dotnet-trace collect-linux -p 2209 ---
[ERROR] Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException:
Unable to connect to Process 2209. ...
   at PidIpcEndpoint.GetDefaultAddress(Int32 pid) in IpcTransport.cs:line 367
   at CollectLinuxCommandHandler.CollectLinux(...) in CollectLinuxCommand.cs:line 95

--- TEST B6: dotnet-counters monitor -p 2209 ---
Unhandled exception: Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException:
Unable to connect to Process 2209. ...
   at PidIpcEndpoint.GetDefaultAddress(Int32 pid) in IpcTransport.cs:line 367
   at CounterMonitor.Monitor(...) in CounterMonitor.cs:line 220

--- TEST B7: dotnet-stack report -p 2209 ---
[ERROR] Microsoft.Diagnostics.NETCore.Client.ServerNotAvailableException:
Unable to connect to Process 2209. ...
   at PidIpcEndpoint.GetDefaultAddress(Int32 pid) in IpcTransport.cs:line 367
   at ReportCommandHandler.Report(...) in ReportCommand.cs:line 52

--- TEST B8: dotnet-dump collect -p 2209 ---
Writing full to /tmp/baseline-dump.dmp
Unable to connect to Process 2209. ...

Fix: Built Tools from cross-namespace-ipc Branch

All tools successfully discover and connect to the cross-namespace process. The collect-linux tests connect successfully but report a runtime version mismatch (target runs 10.0.0-preview.7, collect-linux requires 10.0.0 RTM) — this is expected behavior, not a connection failure.

# Tool Command Result
F1 dotnet-trace ps 2209 dotnet dotnet TargetApp.dll
F2 dotnet-counters ps 2209 dotnet dotnet TargetApp.dll
F3 dotnet-trace collect -p 2209 --duration 5s Trace completed. (404KB nettrace)
F4 dotnet-trace collect-linux --probe -p 2209 ✅ Connected, reported version mismatch (not a connection error)
F5 dotnet-trace collect-linux -p 2209 --duration 5s ✅ Connected, reported version mismatch (not a connection error)
F6 dotnet-counters monitor -p 2209 --duration 5 Status: Running (collected ~30 counter updates)
F7 dotnet-stack report -p 2209 ✅ Printed 3 thread stacks including TargetApp!Program.<Main>$
F8 dotnet-dump collect -p 2209 Complete (dump written)

Key difference for collect-linux: Baseline throws ServerNotAvailableException (can't find socket). Fix successfully connects and gets past to the version check, which correctly identifies the preview runtime as unsupported.

Full fix output
--- TEST F1: dotnet-trace ps ---
 2209  dotnet  /usr/share/dotnet/dotnet  dotnet TargetApp.dll

--- TEST F2: dotnet-counters ps ---
 2209  dotnet  /usr/share/dotnet/dotnet  dotnet TargetApp.dll

--- TEST F3: dotnet-trace collect -p 2209 ---
No profile or providers specified, defaulting to trace profiles 'dotnet-common' + 'dotnet-sampled-thread-time'.
Process        : /usr/share/dotnet/dotnet
Output File    : /tmp/fix-trace.nettrace
Trace Duration : 00:00:00:05
Stopping the trace. This may take several minutes depending on the application being traced.
Trace completed.

--- TEST F4: dotnet-trace collect-linux --probe -p 2209 ---
.NET process 'dotnet (2209)' does NOT support the EventPipe UserEvents IPC command
used by collect-linux. Required runtime: '10.0.0'. Detected runtime: '10.0.0-preview.7.25380.108'.

--- TEST F5: dotnet-trace collect-linux -p 2209 ---
[ERROR] Process 'dotnet (2209)' cannot be traced by collect-linux.
Required runtime: 10.0.0. Detected runtime: 10.0.0-preview.7.25380.108

--- TEST F6: dotnet-counters monitor -p 2209 ---
--counters is unspecified. Monitoring System.Runtime counters by default.
Status: Running (collected ~30 counter updates over 5s)

--- TEST F7: dotnet-stack report -p 2209 ---
Thread (0x1):
  [Native Frames]
  System.Private.CoreLib!System.Threading.Thread.Sleep(int32)
  TargetApp!Program.<Main>$(class System.String[])

Thread (0x14):
  System.Private.CoreLib!System.Diagnostics.Tracing.CounterGroup.PollForValues()

Thread (0x15):
  System.Diagnostics.DiagnosticSource!System.Diagnostics.Metrics.AggregationManager.CollectWorker()

--- TEST F8: dotnet-dump collect -p 2209 ---
Writing full to /tmp/fix-dump.dmp
Complete

mdh1418 and others added 3 commits February 20, 2026 21:51
When a diagnostic tool runs in a container with 'pid: host', the target
process's IPC socket is named using its container-internal PID (NSpid)
and is located under /proc/{hostPid}/root/{tmpdir}/.

Add TryGetNamespacePid() to detect cross-namespace processes via
/proc/{pid}/status NSpid and GetProcessTmpDir() to read TMPDIR from
/proc/{pid}/environ. Both self-guard for Linux, returning safe defaults
on other platforms.

Merge TryGetDefaultAddress and the new TryGetAddressFromPath into a
single TryResolveAddress that handles both Windows named pipes and
Unix domain sockets. This eliminates the duplicated non-Windows socket
search logic that existed in the original TryGetDefaultAddress.

GetDefaultAddress now has a platform-agnostic flow: try cross-namespace
first (no-op on non-Linux), then fall back to local resolution.

Improve the connection error message with Linux-specific guidance for
container scenarios (pid:host, CAP_SYS_PTRACE).
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Extend GetPublishedProcesses() to discover .NET processes in different
PID namespaces by scanning /proc for cross-namespace diagnostic sockets.

Introduce ProcPath and GetDiagnosticSocketSearchPattern() in
PidIpcEndpoint to avoid hardcoding /proc and the socket naming convention
in the enumeration logic.

Refactor both GetLocalPublishedProcesses() and
GetCrossNamespacePublishedProcesses() to be self-contained: each handles
its own file listing, exception handling, and returns a list of PIDs.
GetPublishedProcesses() is now a clean symmetric union of both methods.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Extract TryParseNamespacePid() and ParseTmpDir() from their I/O wrapper
methods to make the parsing logic independently testable with synthetic
data.

Add PidIpcEndpointTests with two categories of tests:

Parsing tests (platform-independent, synthetic data):
- NSpid parsing: cross-namespace, same namespace, nested containers,
  missing NSpid line, empty input, malformed values
- TMPDIR parsing: set, not set, empty environ
- GetDiagnosticSocketSearchPattern: format verification

Behavioral tests (platform-specific via ConditionalFact):
- TryGetNamespacePid on current process returns false (same namespace)
- TryGetNamespacePid on non-Linux returns false (platform guard)
- GetProcessTmpDir reads TMPDIR from a spawned child process
- GetDefaultAddress throws ServerNotAvailableException for non-existent PID
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@mdh1418 mdh1418 requested a review from a team as a code owner February 20, 2026 21:55
Copilot AI review requested due to automatic review settings February 20, 2026 21:55
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds Linux cross-container (cross-PID-namespace) diagnostic IPC resolution to Microsoft.Diagnostics.NETCore.Client so the diagnostic tools can attach to processes whose diagnostic socket lives under /proc/{hostPid}/root/{tmpdir}/ and is named with the container-internal PID (NSpid).

Changes:

  • Add Linux /proc-based helpers to resolve diagnostic socket paths across PID namespaces (NSpid + TMPDIR).
  • Extend GetPublishedProcesses() to enumerate both local and cross-namespace published processes.
  • Add unit tests covering parsing and selected behavioral scenarios; add XUnit extensions dependency.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/IpcTransport.cs Adds cross-namespace PID/TMPDIR parsing and cross-root socket resolution in GetDefaultAddress.
src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsClient/DiagnosticsClient.cs Updates process discovery to union local /tmp sockets and cross-namespace /proc/*/root/... sockets.
src/tests/Microsoft.Diagnostics.NETCore.Client/PidIpcEndpointTests.cs Adds parsing/behavioral tests for namespace PID + TMPDIR logic and error paths.
src/tests/Microsoft.Diagnostics.NETCore.Client/Microsoft.Diagnostics.NETCore.Client.UnitTests.csproj Adds Microsoft.DotNet.XUnitExtensions package for [ConditionalFact].

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +400 to +410
foreach (string line in statusLines)
{
if (line.StartsWith("NSpid:\t", StringComparison.Ordinal))
{
string[] parts = line.Substring(7).Split(new[] { '\t' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length > 1 && int.TryParse(parts[parts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int parsedPid))
{
nsPid = parsedPid;
return true;
}
return false;
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

TryParseNamespacePid is overly strict about the /proc/{pid}/status format: it only matches lines starting with "NSpid:\t" and splits only on tabs, but cat|grep output (and your own remark example) can contain spaces/variable whitespace. Consider matching "NSpid:" and splitting on generic whitespace so cross-namespace detection doesn't silently fail on systems that don't use tab separators.

Copilot uses AI. Check for mistakes.
Comment on lines +405 to +409
if (parts.Length > 1 && int.TryParse(parts[parts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int parsedPid))
{
nsPid = parsedPid;
return true;
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

TryParseNamespacePid currently returns true whenever the NSpid field has more than one value, even if the innermost PID ends up equal to hostPid (or if the first value doesn't match hostPid). To avoid false positives and unnecessary cross-namespace probing, consider returning true only when the parsed innermost PID is different from hostPid (and optionally validate the first value matches hostPid).

Suggested change
if (parts.Length > 1 && int.TryParse(parts[parts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int parsedPid))
{
nsPid = parsedPid;
return true;
}
if (parts.Length > 1)
{
// Optionally validate that the first NSpid value matches the host PID.
if (!int.TryParse(parts[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out int firstPid) || firstPid != hostPid)
{
return false;
}
// Only consider this a different namespace if the innermost PID is different from hostPid.
if (int.TryParse(parts[parts.Length - 1], NumberStyles.Integer, CultureInfo.InvariantCulture, out int parsedPid) && parsedPid != hostPid)
{
nsPid = parsedPid;
return true;
}
return false;
}

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

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

I disagree with copilot here. This method's job is to report the pid in the innermost namespace, whatever it happens to be. Its the caller's job to decide what to do with it. I am not aware that Linux does anything which would prevent a process from having the same ID in more than one namespace. Assuming that same ID implies same namespace seems incorrect.

Comment on lines +472 to 473
if (TryResolveAddress($"{GetProcessRootPath(pid)}{GetProcessTmpDir(pid)}", nsPid, out string crossNsAddress))
{
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

The cross-namespace base path is built via string concatenation: $"{GetProcessRootPath(pid)}{GetProcessTmpDir(pid)}". This assumes TMPDIR is always an absolute path starting with /. If the target process has a relative TMPDIR, this will produce an invalid path (e.g., /proc/{pid}/roottmp). Consider normalizing by ensuring TMPDIR is rooted and using Path.Combine (after trimming any leading directory separator) for correctness.

Suggested change
if (TryResolveAddress($"{GetProcessRootPath(pid)}{GetProcessTmpDir(pid)}", nsPid, out string crossNsAddress))
{
string rootPath = GetProcessRootPath(pid);
string tmpDir = GetProcessTmpDir(pid);
if (Path.IsPathRooted(tmpDir))
{
tmpDir = tmpDir.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
}
string crossNsBasePath = Path.Combine(rootPath, tmpDir);
if (TryResolveAddress(crossNsBasePath, nsPid, out string crossNsAddress))
{

Copilot uses AI. Check for mistakes.
Comment on lines +493 to 497
string[] procEntries;
try
{
string[] files = Directory.GetFiles(PidIpcEndpoint.IpcRootPath);
return GetAllPublishedProcesses(files).Distinct();
procEntries = Directory.GetDirectories(PidIpcEndpoint.ProcPath);
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

GetCrossNamespacePublishedProcesses allocates the full /proc directory list via Directory.GetDirectories(...). On busy hosts this can be a large allocation and makes GetPublishedProcesses() more expensive. Consider switching to Directory.EnumerateDirectories(...) (streaming) and avoiding work for non-numeric entries to reduce memory/latency for dotnet-*-ps scenarios.

Copilot uses AI. Check for mistakes.
try
{
string result = PidIpcEndpoint.GetProcessTmpDir(child.Id);
Assert.Equal(customTmpDir, result);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

GetProcessTmpDir_ChildProcess_ReadsTmpdir assumes /proc/{pid}/environ is readable for the spawned process. On Linux systems with tightened /proc permissions (e.g., hidepid, Yama ptrace restrictions), GetProcessTmpDir will hit its catch-all and fall back to Path.GetTempPath(), causing this test to fail. Consider skipping when /proc/{childPid}/environ can't be read, or loosening the assertion to accept the fallback when access is denied.

Suggested change
Assert.Equal(customTmpDir, result);
// Prefer the TMPDIR value from the child process, but on systems with
// tightened /proc permissions GetProcessTmpDir may fall back to the
// default temporary directory.
if (result == customTmpDir)
{
return;
}
string fallbackTmpDir = Path.GetTempPath();
Assert.Equal(fallbackTmpDir, result);

Copilot uses AI. Check for mistakes.
discoveredPids.Add(hostPid);
}
}
catch { }
Copy link
Member

Choose a reason for hiding this comment

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

When using catch all we should make the try block as narrow as possible to reduce the risk that we catch errors we didn't intend to catch. I assume the catch all is only needed for Directory.GetFiles()? My suggestion above would remove the call entirely, but if it does stick around I'd either narrow the try to only wrap that one line or narrow the catch block to specific Exception types we expect Directory.GetFiles would throw.

Proccess.GetProcessById() also throws but we know the benign Exception type we are looking for is ArgumentException. Given its called in multiple places it would be nice to factor it out into a little helper method CheckProcessExists(int pid) that can do the try/catch and convert it to a boolean result.

try
{
string crossNsPath = $"{PidIpcEndpoint.GetProcessRootPath(hostPid)}{PidIpcEndpoint.GetProcessTmpDir(hostPid)}";
string[] files = Directory.GetFiles(crossNsPath, PidIpcEndpoint.GetDiagnosticSocketSearchPattern(nsPid));
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 like it is doing similar logic to TryResolveAddress except TryResolveAddress handles the possibility that a past process might have had the same NSPID leading to multiple files that match the pattern. I think you'd be better off calling TryResolveAddress to handle it robustly.


private static bool TryGetDefaultAddress(int pid, out string defaultAddress)
/// <summary>
/// Searches a base path for a diagnostic endpoint matching the given PID.
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
/// Searches a base path for a diagnostic endpoint matching the given PID.
/// Searches files in a directory for a diagnostic endpoint matching the given PID.

Maybe its just me, but "searches a base path" seemed ambiguous. This seems clearer.

/// Searches a base path for a diagnostic endpoint matching the given PID.
/// On Windows, resolves named pipes. On other platforms, searches for Unix domain sockets.
/// </summary>
private static bool TryResolveAddress(string basePath, int pid, out string address)
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
private static bool TryResolveAddress(string basePath, int pid, out string address)
private static bool TryResolveAddress(string searchDirectory, int pid, out string address)

{
return TryParseNamespacePid(File.ReadLines(string.Format(_procStatusPathFormat, hostPid)), hostPid, out nsPid);
}
catch { }
Copy link
Member

Choose a reason for hiding this comment

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

This try/catch shouldn't be here. If the exception was anticipated TryParse should already have caught it and converted it to a false return value. Unexpected exceptions shouldn't be caught in most cases because it obscures buggy code and makes diagnosis harder.

{
return ParseTmpDir(File.ReadAllBytes(string.Format(_procEnvironPathFormat, hostPid)));
}
catch { }
Copy link
Member

Choose a reason for hiding this comment

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

Narrow this to only put File.ReadAllBytes() in the try/catch.

}

return defaultAddress;
if (TryResolveAddress(IpcRootPath, pid, out string localAddress))
Copy link
Member

Choose a reason for hiding this comment

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

Processes in the same namespace can also have modified TMP_DIR. Now that we have TMP_DIR checking we should use it everywhere.

discoveredPids.Add(pid);
}

foreach (int pid in GetCrossNamespacePublishedProcesses())
Copy link
Member

Choose a reason for hiding this comment

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

GetLocalPublishedProcesses only finds processes that have the same tmp dir as our current process. Ideally this extra search in /proc/ finds not only the cross namespace processes but also the same container processes with modified TMP_DIR.

msg += " The diagnostic socket path may exceed the 108-character limit."
+ " Try setting TMPDIR to a shorter path.";
}
msg += $" Ensure {IpcRootPath} is writable by the current user."
Copy link
Member

Choose a reason for hiding this comment

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

This part of the message assumes IpcRootDir == target process TMP_DIR which may be false. Its the target process tmp dir which needs to be writable.

+ " Try setting TMPDIR to a shorter path.";
}
msg += $" Ensure {IpcRootPath} is writable by the current user."
+ " If the target process sets TMPDIR, set it to the same directory.";
Copy link
Member

Choose a reason for hiding this comment

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

We only need to include this in the message if either:

  • we aren't on Linux
  • attempting to access /proc/pid/environ failed.

If we can access environ then we know exactly whether the target has a TMP_DIR rather than needing to have the user speculate about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[dotnet-trace][collect-linux] Unable to specifically trace a cross-container process

2 participants