diff --git a/src/devices/src/virtio/net/unixgram.rs b/src/devices/src/virtio/net/unixgram.rs index 78955d202..21f70a405 100644 --- a/src/devices/src/virtio/net/unixgram.rs +++ b/src/devices/src/virtio/net/unixgram.rs @@ -19,11 +19,40 @@ pub struct Unixgram { impl Unixgram { /// Create the backend with a pre-established connection to the userspace network proxy. pub fn new(fd: RawFd) -> Self { + // Ensure the socket is in non-blocking mode. + match fcntl(fd, FcntlArg::F_GETFL) { + Ok(flags) => match OFlag::from_bits(flags) { + Some(flags) => { + if let Err(e) = fcntl(fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK)) { + warn!("error switching to non-blocking: id={fd}, err={e}"); + } + } + None => error!("invalid fd flags id={fd}"), + }, + Err(e) => error!("couldn't obtain fd flags id={fd}, err={e}"), + }; + + #[cfg(target_os = "macos")] + { + // nix doesn't provide an abstraction for SO_NOSIGPIPE, fall back to libc. + let option_value: libc::c_int = 1; + unsafe { + libc::setsockopt( + fd, + libc::SOL_SOCKET, + libc::SO_NOSIGPIPE, + &option_value as *const _ as *const libc::c_void, + std::mem::size_of_val(&option_value) as libc::socklen_t, + ) + }; + } + Self { fd } } /// Create the backend opening a connection to the userspace network proxy. pub fn open(path: PathBuf, send_vfkit_magic: bool) -> Result { + // We cannot create a non-blocking socket on macOS here. This is done later in new(). let fd = socket( AddressFamily::Unix, SockType::Datagram, @@ -47,34 +76,6 @@ impl Unixgram { send(fd, &VFKIT_MAGIC, MsgFlags::empty()).map_err(ConnectError::SendingMagic)?; } - // macOS forces us to do this here instead of just using SockFlag::SOCK_NONBLOCK above. - match fcntl(fd, FcntlArg::F_GETFL) { - Ok(flags) => match OFlag::from_bits(flags) { - Some(flags) => { - if let Err(e) = fcntl(fd, FcntlArg::F_SETFL(flags | OFlag::O_NONBLOCK)) { - warn!("error switching to non-blocking: id={fd}, err={e}"); - } - } - None => error!("invalid fd flags id={fd}"), - }, - Err(e) => error!("couldn't obtain fd flags id={fd}, err={e}"), - }; - - #[cfg(target_os = "macos")] - { - // nix doesn't provide an abstraction for SO_NOSIGPIPE, fall back to libc. - let option_value: libc::c_int = 1; - unsafe { - libc::setsockopt( - fd, - libc::SOL_SOCKET, - libc::SO_NOSIGPIPE, - &option_value as *const _ as *const libc::c_void, - std::mem::size_of_val(&option_value) as libc::socklen_t, - ) - }; - } - if let Err(e) = setsockopt(fd, sockopt::SndBuf, &(7 * 1024 * 1024)) { log::warn!("Failed to increase SO_SNDBUF (performance may be decreased): {e}"); }