Skip to content

Commit dd22bde

Browse files
author
germaniuss
committed
🧵zb : Use async versions of UnixStream when possible
When connecting to a UnixSocket a blocking/threaded API is being used. This commit changes this to use `tokio::net::UnixStream` and `Async<std::os::unix::net::UnixStream>` when possible preventing the use of extra threads. The windows version continues using the blocking/threaded API. The `UnixStream::connect_addr` function from `SocketAddrExt` is no longer used since neither tokio nor async-io supports it. Instead, we use the plain `connect` functions in both environments, since they allow for abstract names when the path is prepended with '\0' (a null byte).
1 parent 744a878 commit dd22bde

2 files changed

Lines changed: 34 additions & 53 deletions

File tree

‎zbus/src/address/transport/mod.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ pub(crate) enum Stream {
226226
#[derive(Debug)]
227227
pub(crate) enum Stream {
228228
#[cfg(unix)]
229-
Unix(tokio::net::UnixStream),
229+
Unix(UnixStream),
230230
#[cfg(unix)]
231231
Unixexec(Command),
232232
Tcp(TcpStream),

‎zbus/src/address/transport/unix.rs‎

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ use super::encode_percents;
1515
#[cfg(not(feature = "tokio"))]
1616
use async_io::Async;
1717

18-
#[cfg(target_os = "linux")]
19-
use std::os::linux::net::SocketAddrExt;
20-
#[cfg(unix)]
21-
use std::os::unix::net::SocketAddr;
22-
#[cfg(unix)]
18+
#[cfg(all(unix, not(feature = "tokio")))]
2319
pub use std::os::unix::net::UnixStream;
20+
#[cfg(all(unix, feature = "tokio"))]
21+
pub use tokio::net::UnixStream;
2422
#[cfg(windows)]
2523
pub use uds_windows::UnixStream;
2624

@@ -46,26 +44,18 @@ impl Unix {
4644
self.path
4745
}
4846

49-
#[cfg(all(windows, not(feature = "tokio")))]
47+
#[cfg(any(unix, not(feature = "tokio")))]
5048
fn take_addr(self) -> Result<PathBuf> {
51-
// This is a `path` in case of Windows until uds_windows provides the needed API:
52-
// https://github.com/haraldh/rust_uds_windows/issues/14
49+
// This is a `path` because neither uds_windows, tokio, nor async_io provide
50+
// the SocketAddrExt functions.
5351
match self.take_path() {
5452
UnixSocket::File(path) => Ok(path),
55-
UnixSocket::Dir(_) | UnixSocket::TmpDir(_) => {
56-
// You can't connect to a unix:dir.
57-
Err(Error::Unsupported)
58-
}
59-
}
60-
}
61-
62-
#[cfg(unix)]
63-
fn take_addr(self) -> Result<SocketAddr> {
64-
match self.take_path() {
65-
UnixSocket::File(path) => Ok(SocketAddr::from_pathname(path)?),
6653
#[cfg(target_os = "linux")]
6754
UnixSocket::Abstract(name) => {
68-
Ok(SocketAddr::from_abstract_name(name.as_encoded_bytes())?)
55+
use std::{ffi::OsString, os::unix::ffi::OsStringExt, path::PathBuf};
56+
let mut v = name.into_vec();
57+
v.insert(0, 0);
58+
Ok(PathBuf::from(OsString::from_vec(v)))
6959
}
7060
UnixSocket::Dir(_) | UnixSocket::TmpDir(_) => {
7161
// You can't connect to a unix:dir.
@@ -103,42 +93,33 @@ impl Unix {
10393
pub(super) async fn connect(self) -> Result<Async<UnixStream>> {
10494
let addr = self.take_addr()?;
10595

106-
let stream = crate::Task::spawn_blocking(
107-
move || -> Result<_> {
108-
#[cfg(unix)]
109-
let stream = UnixStream::connect_addr(&addr)?;
110-
#[cfg(windows)]
111-
let stream = UnixStream::connect(addr)?;
112-
stream.set_nonblocking(true)?;
113-
114-
Ok(stream)
115-
},
116-
"unix stream connection",
117-
)
118-
.await??;
119-
120-
Async::new(stream).map_err(|e| Error::InputOutput(e.into()))
96+
#[cfg(unix)]
97+
let stream = Async::<UnixStream>::connect(addr).await;
98+
99+
#[cfg(not(unix))]
100+
let stream = {
101+
let stream = crate::Task::spawn_blocking(
102+
move || -> Result<_> {
103+
let stream = UnixStream::connect(addr)?;
104+
stream.set_nonblocking(true)?;
105+
106+
Ok(stream)
107+
},
108+
"unix stream connection",
109+
)
110+
.await??;
111+
Async::new(stream)
112+
};
113+
114+
stream.map_err(|e| Error::InputOutput(e.into()))
121115
}
122116

123117
#[cfg(all(unix, feature = "tokio"))]
124-
pub(super) async fn connect(self) -> Result<tokio::net::UnixStream> {
118+
pub(super) async fn connect(self) -> Result<UnixStream> {
125119
let addr = self.take_addr()?;
126-
127-
let stream = crate::Task::spawn_blocking(
128-
move || -> Result<_> {
129-
#[cfg(unix)]
130-
let stream = UnixStream::connect_addr(&addr)?;
131-
#[cfg(windows)]
132-
let stream = UnixStream::connect(addr)?;
133-
stream.set_nonblocking(true)?;
134-
135-
Ok(stream)
136-
},
137-
"unix stream connection",
138-
)
139-
.await??;
140-
141-
tokio::net::UnixStream::from_std(stream).map_err(|e| Error::InputOutput(e.into()))
120+
UnixStream::connect(addr)
121+
.await
122+
.map_err(|e| Error::InputOutput(e.into()))
142123
}
143124
}
144125

0 commit comments

Comments
 (0)