Signal EOF when disabling Softnet control

This commit is contained in:
Fedor Korotkov 2026-07-21 14:03:39 -04:00
parent eda030c347
commit 6fe0db016d
2 changed files with 28 additions and 1 deletions

View File

@ -15,6 +15,7 @@ use smoltcp::wire::Ipv4Address;
use std::collections::HashSet;
use std::io::{self, ErrorKind, Read, Write};
use std::mem::{size_of, zeroed};
use std::net::Shutdown;
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::net::UnixStream;
@ -311,6 +312,12 @@ impl Control {
Ok(!self.input_closed || !self.output.is_empty())
}
pub(super) fn shutdown(&self) -> Result<()> {
self.stream
.shutdown(Shutdown::Both)
.context("failed to shut down the control socket")
}
fn process_input(&mut self, policy: &mut Policy) -> Result<()> {
loop {
if self.discarding_input {
@ -1138,4 +1145,20 @@ mod tests {
drop(control);
assert!(unsafe { libc::fcntl(stream.as_raw_fd(), libc::F_GETFD) != -1 });
}
#[test]
fn shutdown_signals_eof_while_the_original_descriptor_remains_open() {
let (mut client, server) = UnixStream::pair().unwrap();
client
.set_read_timeout(Some(Duration::from_secs(1)))
.unwrap();
let control = Control::new(server.as_raw_fd()).unwrap();
control.shutdown().unwrap();
drop(control);
assert!(unsafe { libc::fcntl(server.as_raw_fd(), libc::F_GETFD) != -1 });
let mut response = [0; 1];
assert_eq!(client.read(&mut response).unwrap(), 0);
}
}

View File

@ -221,7 +221,11 @@ impl Proxy<'_> {
log::warn!("failed to remove Softnet control socket from the poller: {err:#}");
}
self.control = None;
if let Some(control) = self.control.take()
&& let Err(err) = control.shutdown()
{
log::warn!("failed to shut down Softnet control socket: {err:#}");
}
}
}