dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.98k stars 4.66k forks source link

add support for abstract namespaces in Unix domain sockets #77931

Closed cataggar closed 1 year ago

cataggar commented 1 year ago

It would be wonderful if support for abstract namespaces in Unix domain sockets was added.

Tracking Issue for abstract namespaces in Unix domain sockets #85410 Traditionally, Unix domain sockets (UDS) use a file to coordinate socket binding and connecting. On Linux, though, a specific extension exists to allow domain sockets to be created from a namespace which does not use the filesystem. https://github.com/rust-lang/rust/issues/85410

Support for "Linux abstract socket namespace" has been in Python since version 2.5 2006. https://stackoverflow.com/a/27073584/23059

~This is something that may benefit several WSL scenarios. https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ https://devblogs.microsoft.com/commandline/windowswsl-interop-with-af_unix/~

ghost commented 1 year ago

Tagging subscribers to this area: @dotnet/ncl See info in area-owners.md if you want to be subscribed.

Issue Details
It would be wonderful if support for abstract namespaces in Unix domain sockets was added. > Tracking Issue for abstract namespaces in Unix domain sockets #85410 Traditionally, Unix domain sockets (UDS) use a file to coordinate socket binding and connecting. On Linux, though, a specific extension exists to allow domain sockets to be created from a namespace which does not use the filesystem. https://github.com/rust-lang/rust/issues/85410 > Support for "Linux abstract socket namespace" has been in Python since version 2.5 2006. https://stackoverflow.com/a/27073584/23059 This is something that may benefit several WSL scenarios. https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ https://devblogs.microsoft.com/commandline/windowswsl-interop-with-af_unix/
Author: cataggar
Assignees: -
Labels: `area-System.Net.Sockets`
Milestone: -
cataggar commented 1 year ago

In my current use case, I was able to start mdsd (Geneva Logs) on WSL2 only when using its -u flag which "Use abstract domain sockets instead of file system paths". You can see that they are not on the filesystem, but the names are seen when using netstat -a:

cataggar@DESKTOP-VTIN789:/mnt/c/Users/cataggar/geneva$ netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 localhost:29130         0.0.0.0:*               LISTEN
tcp        0      0 localhost:29230         0.0.0.0:*               LISTEN
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     31834    @/home/cataggar/mdsd_fluent.socket@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
unix  2      [ ACC ]     SEQPACKET  LISTENING     18539    /run/WSL/8_interop
unix  2      [ ACC ]     SEQPACKET  LISTENING     19475    /run/WSL/309_interop
unix  2      [ ACC ]     STREAM     LISTENING     31829    @/home/cataggar/mdsd_bond.socket@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
unix  2      [ ACC ]     SEQPACKET  LISTENING     20006    /run/WSL/2677_interop
unix  2      [ ]         DGRAM                    31836    @/home/cataggar/mdsd_syslog.socket@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
unix  2      [ ACC ]     STREAM     LISTENING     31830    @/home/cataggar/mdsd_djson.socket@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
unix  2      [ ACC ]     STREAM     LISTENING     31835    @/home/cataggar/mdsd_influx.socket@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
unix  2      [ ACC ]     STREAM     LISTENING     31831    @/home/cataggar/mdsd_json.socket@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
cataggar@DESKTOP-VTIN789:/mnt/c/Users/cataggar/geneva$ ls /home/cataggar
mdsd.lock  mdsd.pidport  vsdbg

Unfortunately, I can't connect to it using the GenevaExporter.

cataggar@DESKTOP-VTIN789:/mnt/c/Users/cataggar/geneva$ dotnet run
Unhandled exception. System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (99): Cannot assign requested address /home/cataggar/mdsd_fluent.socket
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.Connect(EndPoint remoteEP)
   at OpenTelemetry.Exporter.Geneva.UnixDomainSocketDataTransport.Connect()
   at OpenTelemetry.Exporter.Geneva.GenevaLogExporter..ctor(GenevaExporterOptions options)
   at Microsoft.Extensions.Logging.GenevaLoggingExtensions.AddGenevaLogExporter(OpenTelemetryLoggerOptions options, Action`1 configure)
   at Program.<>c.<<Main>$>b__0_2(OpenTelemetryLoggerOptions openTelemetryLogger) in /mnt/c/Users/cataggar/geneva/Program.cs:line 9

Program.cs

   using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

using IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
        logging.AddOpenTelemetry(openTelemetryLogger=>
        {
            openTelemetryLogger.AddGenevaLogExporter(genevaExporter =>
            {
                genevaExporter.ConnectionString = "Endpoint=unix:/home/cataggar/mdsd_fluent.socket";
            });
        })
    )
    .ConfigureServices((_, services) =>
        services.AddHostedService<Worker>()
     )
    .Build();

await host.RunAsync();

internal class Worker : IHostedService
{
    ILogger log;
    public Worker(ILogger<Worker> log)
    {
        this.log = log;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        log.LogInformation("start");
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        log.LogInformation("stop");
        return Task.CompletedTask;
    }
}

csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
    <!-- The releases in August allows setting the TraceFlags, but avoids updating System.Diagnostics.DiagnosticSource -->
    <!-- https://github.com/open-telemetry/opentelemetry-dotnet/blob/main/src/OpenTelemetry.Api/CHANGELOG.md -->
    <PackageReference Include="OpenTelemetry.Api" Version="1.4.0-alpha.1" />
    <PackageReference Include="OpenTelemetry.Exporter.Geneva" Version="1.3.0" />
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.0.0-rc9.5" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.0.0-rc9.5" />
  </ItemGroup>
</Project>
stephentoub commented 1 year ago

It would be wonderful if support for abstract namespaces in Unix domain sockets was added.

They're already supported on Linux and have been for years. Can you elaborate on what doesn't work? Paths that begin with null '\0' are abstract, e.g. https://github.com/dotnet/runtime/blob/15f015f884d27372fbffc984b2cee58c64ae2d80/src/libraries/System.Net.Sockets/tests/FunctionalTests/UnixDomainSocketTest.cs#L389-L404

fbrosseau commented 1 year ago

This is something that may benefit several WSL scenarios.

Unix sockets were supported as an interoperability bridge between Linux and Windows under WSL1. Unless things changed recently, they killed them in WSL2. Using WSL1 today is very niche (and I would not be surprised if they kill it altogether at some point).

Of course they do work in WSL2, but not as Windows<->Linux interopability anymore. Just local to Linux, as in any Linux system.

For portable zero-conf networking today (ie, avoiding TCP for some reason), the preferred method would be AF_HYPERV+AF_VSOCK.

wfurt commented 1 year ago

I think this is because for isolation win WSL2 -> I'm not sure we can cross the OS boundaries inside of .NET. Adding better support for the "virtual" families may be way to go.

antonfirsov commented 1 year ago

We have #58378 to track AF_HYPERV+AF_VSOCK. Otherwise, this looks like a WSL issue. Or is there anything else the .NET runtime/BCL could improve here @cataggar?

ghost commented 1 year ago

This issue has been marked needs-author-action and may be missing some important information.

cataggar commented 1 year ago

It is not a WSL issue. Forget that I mentioned WSL at all. Can support be added for Linux abstract namespaces in Unix domain sockets?

stephentoub commented 1 year ago

@cataggar, as I noted in https://github.com/dotnet/runtime/issues/77931#issuecomment-1304360062, UnixDomainSocketEndPoint in .NET already supports abstract addresses. What specifically isn't working?

cataggar commented 1 year ago

Thanks for pointing that out again, @stephentoub. Closing this.