Skip to content

Shorten backchannel socket paths#17226

Open
karolz-ms wants to merge 4 commits into
mainfrom
karolz-ms/fix-backchannel-path-length
Open

Shorten backchannel socket paths#17226
karolz-ms wants to merge 4 commits into
mainfrom
karolz-ms/fix-backchannel-path-length

Conversation

@karolz-ms
Copy link
Copy Markdown
Contributor

Description

Fixes #15752

Users with long or non-ASCII home directory paths can exceed the byte-based Unix domain socket path limits when Aspire creates backchannel sockets. This shortens the backchannel socket location and file names so AppHost/CLI communication has more path budget while preserving the visible process ID for debugging.

User-facing usage

No new CLI syntax is required. Existing aspire run and MCP workflows use shorter backchannel socket paths under ~/.aspire/cli/bch/, and the CLI still discovers legacy sockets under ~/.aspire/cli/backchannels/ when connecting to AppHosts built with older libraries.

Implementation details

  • Uses compact base64url identifiers for the AppHost and random instance portions of socket names.
  • Keeps the AppHost PID in decimal form in the socket file name.
  • Validates socket paths by UTF-8 byte length, including the trailing null byte.
  • Adds CLI fallback discovery and cleanup for legacy socket name formats.
  • Watches both compact and legacy backchannel directories so newly-created sockets are detected.

Validation

  • dotnet build tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj --no-restore /p:SkipNativeBuild=true
  • dotnet build tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj --no-restore /p:SkipNativeBuild=true
  • dotnet test --project tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class "*.AppHostHelperTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • dotnet test --project tests\Aspire.Cli.Tests\Aspire.Cli.Tests.csproj --no-launch-profile -- --filter-class "*.CliPathHelperTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • dotnet test --project tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj --no-launch-profile -- --filter-method "*.SocketPathUsesCompactFormat" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • dotnet test --project tests\Aspire.Hosting.Tests\Aspire.Hosting.Tests.csproj --no-build --no-launch-profile -- --filter-class "*.AppHostBackchannelTests" --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 18, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17226

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17226"

@JamesNK
Copy link
Copy Markdown
Member

JamesNK commented May 19, 2026

I'm interested how you make this compatible in both directions. e.g. old CLI vs new app host. Does the app host listen on multiple files?

Also, if introducing a new backchannel format, it would be a good opportunity to make the path hash case insensitive, e.g. on windows convert the path to lower before calculating the hash. I kind of improved it here by making the drive letter consistent. But it would be better if the whole path was case insensitive to avoid related issues.

@karolz-ms
Copy link
Copy Markdown
Contributor Author

I'm interested how you make this compatible in both directions. e.g. old CLI vs new app host. Does the app host listen on multiple files?

I don't. This was discussed at the team meeting yesterday. The approach with this PR is that a new CLI can discover backchannel socket created by older app host, but the old CLI cannot work with newer app host that is using the new backchannel path--you have to upgrade your CLI to make things work. I could not think of a good way to solve the latter use case; I am open to suggestions.

Also, if introducing a new backchannel format, it would be a good opportunity to make the path hash case insensitive, e.g. on windows convert the path to lower before calculating the hash. I kind of improved it here by making the drive letter consistent. But it would be better if the whole path was case insensitive to avoid related issues.

You mean do this on Windows only? I can look into that.

@karolz-ms karolz-ms force-pushed the karolz-ms/fix-backchannel-path-length branch from cf0a045 to c8c6397 Compare May 19, 2026 21:16
@karolz-ms karolz-ms marked this pull request as ready for review May 19, 2026 23:22
Copilot AI review requested due to automatic review settings May 19, 2026 23:22
@karolz-ms
Copy link
Copy Markdown
Contributor Author

Should be ready for review now but need to do some more manual testing because AI testing produced ambiguous results.

Copy link
Copy Markdown
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

This PR updates Aspire’s backchannel socket location and naming to reduce the risk of exceeding Unix domain socket path byte limits (notably with long / non-ASCII home directories), while keeping compatibility with older AppHost/CLI versions.

Changes:

  • Introduces a compact socket directory (~/.aspire/cli/bch/) and compact socket filename format using base64url identifiers plus PID.
  • Adds shared helpers to compute/validate socket paths by UTF-8 byte length (including trailing null) and to discover both compact + legacy sockets.
  • Updates CLI monitoring/discovery and test coverage to account for compact + legacy socket locations/formats.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Tests/Utils/UnixSocketHelper.cs Updates test helper to use shared compact CLI socket path computation.
tests/Aspire.Hosting.Tests/Backchannel/AuxiliaryBackchannelTests.cs Adjusts assertions to the compact socket filename + directory and validates byte-length limit.
tests/Aspire.Cli.Tests/Utils/CliPathHelperTests.cs Updates CLI socket-path tests to expect the new compact directory and compact names.
tests/Aspire.Cli.Tests/Utils/AppHostHelperTests.cs Updates CLI helper tests for compact IDs, legacy discovery, and UTF-8 byte-limit regression coverage.
src/Shared/BackchannelConstants.cs Implements compact IDs/paths, legacy fallback discovery, and byte-length validation helpers shared by AppHost + CLI.
src/Aspire.Hosting/Backchannel/AuxiliaryBackchannelService.cs Updates orphan cleanup and fallback naming to use compact AppHost IDs and legacy cleanup.
src/Aspire.Cli/Utils/CliPathHelper.cs Switches CLI socket creation to use shared compact CLI socket path logic.
src/Aspire.Cli/Utils/AppHostHelper.cs Updates helper docs and adds legacy-hash enumeration wrapper.
src/Aspire.Cli/Commands/AppHostLauncher.cs Extends detached launch discovery to search multiple legacy hashes.
src/Aspire.Cli/Backchannel/AuxiliaryBackchannelMonitor.cs Watches both compact + legacy directories and updates scan logic to handle compact formats.

Comment thread src/Aspire.Cli/Utils/CliPathHelper.cs
Comment thread tests/Aspire.Cli.Tests/Utils/CliPathHelperTests.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI commented May 19, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • c78vsblobprodcus322.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/aspire/aspire/.dotnet/dotnet /home/REDACTED/work/aspire/aspire/.dotnet/dotnet /home/REDACTED/work/aspire/aspire/.dotnet/sdk/10.0.201/MSBuild.dll /noautoresponse /nologo /nodemode:1 /nodeReuse:true /low:false .dotnet//git (dns block)
  • https://api.github.com/repos/microsoft/aspire/pulls/comments/3270309506
    • Triggering command: /usr/bin/gh gh api repos/microsoft/aspire/pulls/comments/3270309506 (http block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (http block)
  • l49vsblobprodcus358.vsblob.vsassets.io
    • Triggering command: /home/REDACTED/work/aspire/aspire/.dotnet/dotnet /home/REDACTED/work/aspire/aspire/.dotnet/dotnet /home/REDACTED/work/aspire/aspire/.dotnet/sdk/10.0.201/MSBuild.dll /noautoresponse /nologo /nodemode:1 /nodeReuse:true /low:false .dotnet//git (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

karolz-ms and others added 4 commits May 20, 2026 08:59
@karolz-ms karolz-ms force-pushed the karolz-ms/fix-backchannel-path-length branch from efee6ac to 40ee29b Compare May 20, 2026 16:00
@karolz-ms
Copy link
Copy Markdown
Contributor Author

Manual and agentic testing complete, all good now

@github-actions
Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 94 passed, 0 failed, 2 unknown (commit 40ee29b)

View all recordings
Status Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View recording
AddPackageWhileAppHostRunningDetached ▶️ View recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View recording
AgentInitCommand_DefaultSelection_InstallsDefaultSkills ▶️ View recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View recording
AllPublishMethodsBuildDockerImages ▶️ View recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View recording
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost ▶️ View recording
AspireInitWithExistingAppHostDirRecreatesMissingNuGetConfigAndPreservesFiles ▶️ View recording
AspireInitWithSolutionFileGeneratesAppHostThatBuildsAgainstChannelHive ▶️ View recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View recording
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent ▶️ View recording
Banner_DisplayedOnFirstRun ▶️ View recording
Banner_DisplayedWithExplicitFlag ▶️ View recording
Banner_NotDisplayedWithNoLogoFlag ▶️ View recording
CertificatesClean_RemovesCertificates ▶️ View recording
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate ▶️ View recording
CertificatesTrust_WithUntrustedCert_TrustsCertificate ▶️ View recording
ConfigSetGet_CreatesNestedJsonFormat ▶️ View recording
CreateAndRunAspireStarterProject ▶️ View recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View recording
CreateAndRunEmptyAppHostProject ▶️ View recording
CreateAndRunJavaEmptyAppHostProject ▶️ View recording
CreateAndRunJsReactProject ▶️ View recording
CreateAndRunPythonReactProject ▶️ View recording
CreateAndRunTypeScriptEmptyAppHostProject ▶️ View recording
CreateAndRunTypeScriptStarterProject ▶️ View recording
CreateJavaAppHostWithViteApp ▶️ View recording
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain ▶️ View recording
DashboardRunWithOtelTracesReturnsNoTraces ▶️ View recording
DeployK8sBasicApiService ▶️ View recording
DeployK8sWithExternalHelmChart ▶️ View recording
DeployK8sWithGarnet ▶️ View recording
DeployK8sWithMongoDB ▶️ View recording
DeployK8sWithMySql ▶️ View recording
DeployK8sWithPostgres ▶️ View recording
DeployK8sWithRabbitMQ ▶️ View recording
DeployK8sWithRedis ▶️ View recording
DeployK8sWithSqlServer ▶️ View recording
DeployK8sWithValkey ▶️ View recording
DeployTypeScriptAppToKubernetes ▶️ View recording
DescribeCommandResolvesReplicaNames ▶️ View recording
DescribeCommandShowsRunningResources ▶️ View recording
DetachFormatJsonProducesValidJson ▶️ View recording
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance ▶️ View recording
DoListStepsShowsPipelineSteps ▶️ View recording
DocsCommand_RendersInteractiveMarkdownFromLocalSource ▶️ View recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View recording
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain ▶️ View recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View recording
GlobalMigration_HandlesCommentsAndTrailingCommas ▶️ View recording
GlobalMigration_HandlesMalformedLegacyJson ▶️ View recording
GlobalMigration_PreservesAllValueTypes ▶️ View recording
GlobalMigration_SkipsWhenNewConfigExists ▶️ View recording
GlobalSettings_MigratedFromLegacyFormat ▶️ View recording
InitTypeScriptAppHost_AugmentsExistingViteRepoAtRoot ▶️ View recording
InteractiveCSharpInitCreatesExpectedFiles ▶️ View recording
InvalidAppHostPathWithComments_IsHealedOnRun ▶️ View recording
JavaScriptHostingApisRunFromTypeScriptAppHost ▶️ View recording
LatestCliCanStartStableChannelAppHost ▶️ View recording
LatestCliCanStartStableChannelTypeScriptAppHost ▶️ View recording
LegacySettingsMigration_AdjustsRelativeAppHostPath ▶️ View recording
LogLevelTrace_ProducesTraceEntriesInCliLogFile ▶️ View recording
LogsCommandShowsResourceLogs ▶️ View recording
OtelLogsReturnsStructuredLogsFromStarterApp ▶️ View recording
OtelLogsReturnsStructuredLogsFromStarterAppIsolated ▶️ View recording
PsCommandListsRunningAppHost ▶️ View recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View recording
PublishWithConfigureEnvFileUpdatesEnvOutput ▶️ View recording
PublishWithDockerComposeServiceCallbackSucceeds ▶️ View recording
PublishWithoutOutputPathUsesAppHostDirectoryDefault ▶️ View recording
ResourceCommand_FailedExecution_DisplaysAppHostLogPathAndLogContainsEntries ▶️ View recording
ResourceCommand_FailsWhenInteractionServiceIsRequired ▶️ View recording
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput ▶️ View recording
RestoreGeneratesSdkFiles ▶️ View recording
RestoreGeneratesSdkFiles_WithConfiguredToolchain ▶️ View recording
RestoreRefreshesGeneratedSdkAfterAddingIntegration ▶️ View recording
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes ▶️ View recording
RunFromParentDirectory_UsesExistingConfigNearAppHost ▶️ View recording
RunPublishFailureScenarioAsync ▶️ View recording
RunReportsSyntaxErrorsForDotNetAppHost ▶️ View recording
RunReportsSyntaxErrorsForTypeScriptAppHost ▶️ View recording
SecretCrudOnDotNetAppHost ▶️ View recording
SecretCrudOnTypeScriptAppHost ▶️ View recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View recording
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets ▶️ View recording
StartReportsSyntaxErrorsForDotNetAppHost ▶️ View recording
StartReportsSyntaxErrorsForTypeScriptAppHost ▶️ View recording
StopAllAppHostsFromAppHostDirectory ▶️ View recording
StopJavaPolyglotAppHostUsingApphostDirectory ▶️ View recording
StopNonInteractiveSingleAppHost ▶️ View recording
StopTypeScriptPolyglotAppHostUsingApphostDirectory ▶️ View recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View recording
UnAwaitedChainsCompileWithAutoResolvePromises ▶️ View recording
UpdateProjectChannelToStable_TypeScript_PicksUpStablePackages ▶️ View recording

📹 Recordings uploaded automatically from CI run #26174406587

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.

Backchannel path is too long

4 participants