Rust: UnixStream doesn't support abstract addresses

Created on 16 May 2017  Â·  19Comments  Â·  Source: rust-lang/rust

From RFC 1479:

Linux's abstract namespace is not supported. Functionality may be added in the future via extension traits in std::os::linux::net.

This feature is described in the Linux unix(7) manpage.

This issue tracks the absence of (and hopefully future development of) this feature.

C-feature-accepted T-libs

All 19 comments

This should be pretty easy to add for anyone that's interested!

Not that easy... I'd probably want to change UnixStream::connect to take a A: Into<SocketAddr> and then impl<T: AsRef<Path>> From<T> for SocketAddr. But, that conversion is fallible (see std::sys::unix::ext::sockaddr_un). So you need TryInto. But then you can't supply a SocketAddr directly until we get impl<T, U> TryFrom<U> for T where T: From<U>, which requires !...

Abstract namespaces are Linux only so we'd only want to make them available through a Linux-only method. Probably something like

pub trait UnixStreamExt {
    fn connect_abstract(name: &[u8]) -> io::Result<UnixStream>;
}

pub trait SocketAddrExt {
    fn as_abstract(&self) -> Option<&[u8]>;
}

That seems like a strange API, to have two different connect functions. You can have it be Linux only to have an extension trait to create a SockAddr on Linux only.

But then you can't supply a SocketAddr directly until we get impl TryFrom for T where T: From, which requires !...

Why is it impossible to implement TryFrom from a type to itself without !?

@sfackler Because we want to indicate that the TryFrom implementation will never fail, so gotta wait until ! is available.

Actually that might still not work, because now you need TryFrom<Err=io::Error> for AsRef<Path> and TryFrom<Err=!> for SocketAddr...

@retep998

  1. ! is not the only way to indicate that. String's FromStr impl has always been infallible: https://doc.rust-lang.org/src/collections/string.rs.html#1829-1852
  2. How is that valuable in any way in practice? When have you ever said, "man, this code I'm trying to write would have been way better if some_socket_addr.to_socket_addrs() returned a Result<T, !> instead of Result<T, io::Error>"? If you're working in a concrete context you're not going to use try_from to go from a type to itself, and if you're in an generic context, you're only going use try_from if you want to deal with the failure case anyway.

I'd advice against using that misfeature. In the past 20 years, I've never seen any practical usecase
for that, and it creates more trouble than it's actually worth it.

@metux practical use-case is interoperability with other software that creates an abstract socket?

Ok. Does anyone here run an application which needs that ? I don't recall any in the last two decades.

Would I have opened this ticket if I didn't?

Would I have opened this ticket if I didn't?

No idea, you didn't tell ;-)

I would love to see a PR implementing Linux-only support for abstract addresses. I believe we will be able to reach agreement in the PR without needing to draft an RFC.

Now that TryFrom and never_type are close to being stabilized, I took another look at this. https://github.com/rust-lang/rust/commit/d47e9796d97df0c75d25efa25b179918208f1ba9

There's a conflicting implementations issue, a P: AsRef<Path> might already implement Into<SocketAddr>:

error[E0119]: conflicting implementations of trait `core::convert::TryFrom<_>` for type `sys::unix::ext::net::SocketAddr`:
  --> src/libstd/sys/unix/ext/net.rs:91:1
   |
91 | impl<P: AsRef<Path>> TryFrom<P> for SocketAddr {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: conflicting implementation in crate `core`:
           - impl<T, U> core::convert::TryFrom<U> for T
             where U: core::convert::Into<T>;

Here is the commit that adds SocketAddrExt https://github.com/rust-lang/rust/commit/c4db0685b181f12c4285dac3d932f1859bba74f5. That should plug right into whatever solution we come up with for the UnixStream API.

I'm interested in this support.

Rather than changing the type of connect (which seems likely to produce inference errors), why not introduce a couple of new methods, bind_addr and connect_addr, which accept a concrete SocketAddr? Those methods could exist on all platforms; only the mechanism to create an abstract SocketAddr needs to be a platform-specific extension.

This would avoid dealing with TryFrom at all, and would avoid introducing potential inference and compatibility issues as well.

I'd like to chime in on this one. There's one neat use case of the abstract namespace and it's implementing robust lock against running in parallel. You try to bind the address and if it's already in use, some other instance is running. Furthermore, unlike the filesystem based ones, these clean up automatically and you don't have to worry about races around unlinking the old (dead) socket „file“.

Sockets with abstract addresses are also often needed to interact with dbus on Linux.
See https://github.com/diwic/dbus-rs/blob/627b42597f13c8f5db3b4259271a5881439c310b/dbus-native/src/sys.rs#L8

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dtolnay picture dtolnay  Â·  3Comments

pedrohjordao picture pedrohjordao  Â·  3Comments

Robbepop picture Robbepop  Â·  3Comments

mcarton picture mcarton  Â·  3Comments

jmegaffin picture jmegaffin  Â·  3Comments