Skip to content

Commit 7ab73dc

Browse files
jakecorrentislp
authored andcommitted
unixgram: Make fd non-blocking
When creating unixgram backend from existing fd we need to make it non-blocking so the user does not have to care about this implementation detail. Disabling SIGPIPE is needed on the existing fd for the same reason. Fix by moving these steps from open() to new(). Authored-by: Nir Soffer <nirsof@gmail.com> Signed-off-by: Nir Soffer <nirsof@gmail.com> Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me> Signed-off-by: Sergio Lopez <slp@redhat.com>
1 parent 57eeb22 commit 7ab73dc

1 file changed

Lines changed: 29 additions & 28 deletions

File tree

src/devices/src/virtio/net/unixgram.rs

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,40 @@ pub struct Unixgram {
1919
impl Unixgram {
2020
/// Create the backend with a pre-established connection to the userspace network proxy.
2121
pub fn new(fd: RawFd) -> Self {
22+
// Ensure the socket is in non-blocking mode.
23+
match fcntl(fd, FcntlArg::F_GETFL) {
24+
Ok(flags) => match OFlag::from_bits(flags) {
25+
Some(flags) => {
26+
if let Err(e) = fcntl(fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK)) {
27+
warn!("error switching to non-blocking: id={fd}, err={e}");
28+
}
29+
}
30+
None => error!("invalid fd flags id={fd}"),
31+
},
32+
Err(e) => error!("couldn't obtain fd flags id={fd}, err={e}"),
33+
};
34+
35+
#[cfg(target_os = "macos")]
36+
{
37+
// nix doesn't provide an abstraction for SO_NOSIGPIPE, fall back to libc.
38+
let option_value: libc::c_int = 1;
39+
unsafe {
40+
libc::setsockopt(
41+
fd,
42+
libc::SOL_SOCKET,
43+
libc::SO_NOSIGPIPE,
44+
&option_value as *const _ as *const libc::c_void,
45+
std::mem::size_of_val(&option_value) as libc::socklen_t,
46+
)
47+
};
48+
}
49+
2250
Self { fd }
2351
}
2452

2553
/// Create the backend opening a connection to the userspace network proxy.
2654
pub fn open(path: PathBuf, send_vfkit_magic: bool) -> Result<Self, ConnectError> {
55+
// We cannot create a non-blocking socket on macOS here. This is done later in new().
2756
let fd = socket(
2857
AddressFamily::Unix,
2958
SockType::Datagram,
@@ -47,34 +76,6 @@ impl Unixgram {
4776
send(fd, &VFKIT_MAGIC, MsgFlags::empty()).map_err(ConnectError::SendingMagic)?;
4877
}
4978

50-
// macOS forces us to do this here instead of just using SockFlag::SOCK_NONBLOCK above.
51-
match fcntl(fd, FcntlArg::F_GETFL) {
52-
Ok(flags) => match OFlag::from_bits(flags) {
53-
Some(flags) => {
54-
if let Err(e) = fcntl(fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK)) {
55-
warn!("error switching to non-blocking: id={fd}, err={e}");
56-
}
57-
}
58-
None => error!("invalid fd flags id={fd}"),
59-
},
60-
Err(e) => error!("couldn't obtain fd flags id={fd}, err={e}"),
61-
};
62-
63-
#[cfg(target_os = "macos")]
64-
{
65-
// nix doesn't provide an abstraction for SO_NOSIGPIPE, fall back to libc.
66-
let option_value: libc::c_int = 1;
67-
unsafe {
68-
libc::setsockopt(
69-
fd,
70-
libc::SOL_SOCKET,
71-
libc::SO_NOSIGPIPE,
72-
&option_value as *const _ as *const libc::c_void,
73-
std::mem::size_of_val(&option_value) as libc::socklen_t,
74-
)
75-
};
76-
}
77-
7879
if let Err(e) = setsockopt(fd, sockopt::SndBuf, &(7 * 1024 * 1024)) {
7980
log::warn!("Failed to increase SO_SNDBUF (performance may be decreased): {e}");
8081
}

0 commit comments

Comments
 (0)