Should we expose Unix sockets from Windows?
I interpret the question asked in this thread as: "How can we add AF_UNIX support for more platforms in the stdlib now that those platforms support it?" To me it seems that supporting a feature on more tier-1 platforms would be desirable, even if we can't yet guarantee that we can provide for all platforms. I think adding Unix socket support for the Windows versions that support it would make Rust code more portable, which is progress overall.
Depending on how we implement this (see below) this could mean that existing code that relies on Unix sockets could suddenly work on Windows as well. Without needing to do anything other than upgrade to a new compiler version. Making existing Rust programs work on more platforms by effectively changing nothing seems really good!
How would we expose Unix sockets on windows?
I'd like to separate the questions of "should we" from the "how would we go about it". I feel pretty strong that it would be a good idea to expose Unix sockets on more platforms. But I'm less sure on what the right way would be to go about it.
What's the current situation?
Unix sockets in the stdlib are currently exported like this:
I see two difficulties with this:
- This is part of
std::os::unix
which is often thought of as a counterpart to std::os::windows
.
- The names of
Incoming
and SocketAddr
conflict with their std::net
counterparts. They cannot live in the same submodule as-is.
Option 1
The first option would be to make std::os::unix::net
available on Windows as well. This would change the meaning of what it means to live under std::os
, but overall this seems like it could be the easiest change for end-users as all existing libraries that depend on Unix sockets would suddenly also work on Windows.
Communication wise there are two tricky parts to handle here:
- How do we communicate that parts of the Unix APIs are now also available on Windows?
- How do we communicate that not all Windows versions are supported?
I've heard libs teams members express how perhaps the std::os::*
submodules may not have been the best design, and at least for these APIs I tend to agree. It seems that it didn't really account for the possibility of platforms gaining support for features from other platforms, which is kind of the root of the awkwardness here.
Option 2
We could introduce a new submodule for the Unix socket APIs. Perhaps something like std::ipc
. This has the benefit of being new, so we can define which guarantees it provides. But it would also be easier to type out since e.g. std::os::unix::net::UnixDatagram
doesn't particularly roll off the tongue.
This approach doesn't need to be mutually exclusive with the first option. We could a path where we introduce a new submodule, and then slowly phase out the std::os::unix::net
family of APIs. Both could refer to the same types under the hood so we'd have the benefit that existing code will work on more platforms. But we take it as an opportunity to improve ergonomics, documentation, and visibility of the APIs.
Option 3
Instead of a new submodule we could add the types to std::net
. However Incoming
and SocketAddr
already exist in std::net
. So we'd have to rename them to UnixSocketAddr
and UnixIncoming
. But the upside of this would be that we could storify it as: "Unix network primitives have become available on more platforms, so they're now available from the main network submodule".
Just like option 2, this doesn't need to be mutually exclusive with the first option and we could provide a path for introducing the new APIs and then slowly deprecating the others.
Discussion
I'm interested in this because I'm currently writing async bindings to named pipes to do cross-platform IPC, and I'm not particularly loving it. Existing code is not very well maintained, and even when using named pipes it's hard to reap the full benefits since we need to account for Unix socket semantics as well.
It'd be nice if Unix sockets were available on more platforms that support them. That would provide a fully portable IPC layer directly from the stdlib. Because right now it seems that Unix sockets are often chosen because they fill that role and are part of the stdlib, but that introduces portability issues for Windows. From a pragmatic perspective I'd prefer we expand support to include some Windows versions instead of the status quo where we have portability problems.
Oh before I forget: WASM was mentioned earlier. It seems the approach the libs team is taking now is to expose all of stdlib in WASI but marking all of their internals as panic!("not implemented for WASI");
. That way the API can gradually be filled out as more APIs become available. I feel what we're discussing in this thread feels in line with that.
Anyway, that's about all I had to share here. I hope what I'm saying here makes sense! If this needs to be driven by someone I can probably warrant spending some cycles here in the next few weeks.