Skip to content

Commit d24a0d3

Browse files
committed
Don't set SO_NOSIGPIPE when accepting sockets
This is inherited from the parent socket. Furthermore when attempting to set it on a Unix socket domain it will result in an error.
1 parent 4af7d3d commit d24a0d3

File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed

src/socket.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ impl Socket {
285285
)))]
286286
{
287287
let (socket, addr) = self.accept_raw()?;
288-
let socket = set_common_flags(socket)?;
288+
let socket = set_common_accept_flags(socket)?;
289289
// `set_common_flags` does not disable inheritance on Windows because `Socket::new`
290290
// unlike `accept` is able to create the socket with inheritance disabled.
291291
#[cfg(windows)]
@@ -762,8 +762,6 @@ const fn set_common_type(ty: Type) -> Type {
762762
}
763763

764764
/// Set `FD_CLOEXEC` and `NOSIGPIPE` on the `socket` for platforms that need it.
765-
#[inline(always)]
766-
#[allow(clippy::unnecessary_wraps)]
767765
fn set_common_flags(socket: Socket) -> io::Result<Socket> {
768766
// On platforms that don't have `SOCK_CLOEXEC` use `FD_CLOEXEC`.
769767
#[cfg(all(
@@ -798,6 +796,34 @@ fn set_common_flags(socket: Socket) -> io::Result<Socket> {
798796
Ok(socket)
799797
}
800798

799+
/// Set `FD_CLOEXEC` on the `socket` for platforms that need it.
800+
///
801+
/// Unlike `set_common_flags` we don't set `NOSIGPIPE` as that is inherited.
802+
/// Furthermore attempts to set it on a unix socket domain results in an error.
803+
fn set_common_accept_flags(socket: Socket) -> io::Result<Socket> {
804+
// On platforms that don't have `SOCK_CLOEXEC` use `FD_CLOEXEC`.
805+
#[cfg(all(
806+
unix,
807+
not(any(
808+
target_os = "android",
809+
target_os = "dragonfly",
810+
target_os = "freebsd",
811+
target_os = "fuchsia",
812+
target_os = "hurd",
813+
target_os = "illumos",
814+
target_os = "linux",
815+
target_os = "netbsd",
816+
target_os = "openbsd",
817+
target_os = "espidf",
818+
target_os = "vita",
819+
target_os = "cygwin",
820+
))
821+
))]
822+
socket._set_cloexec(true)?;
823+
824+
Ok(socket)
825+
}
826+
801827
/// A local interface specified by its index or an address assigned to it.
802828
///
803829
/// `Index(0)` and `Address(Ipv4Addr::UNSPECIFIED)` are equivalent and indicate

tests/socket.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ where
511511
panic!("unexpected error: {}", io::Error::last_os_error());
512512
}
513513
assert_eq!(length as usize, size_of::<libc::c_int>());
514-
assert_eq!(flags, want as _, "non-blocking option");
514+
assert_eq!(flags, want as _);
515515
}
516516

517517
const DATA: &[u8] = b"hello world";
@@ -631,6 +631,30 @@ fn unix() {
631631
assert_eq!(&buf[..n], DATA);
632632
}
633633

634+
#[test]
635+
fn unix_accept() {
636+
if !unix_sockets_supported() {
637+
return;
638+
}
639+
let mut path = env::temp_dir();
640+
path.push("socket2");
641+
let _ = fs::remove_dir_all(&path);
642+
fs::create_dir_all(&path).unwrap();
643+
path.push("unix_accept");
644+
645+
let listener = Socket::new(Domain::UNIX, Type::STREAM, None).unwrap();
646+
listener.bind(&SockAddr::unix(&path).unwrap()).unwrap();
647+
listener.listen(1).unwrap();
648+
649+
Socket::new(Domain::UNIX, Type::STREAM, None)
650+
.unwrap()
651+
.connect(&SockAddr::unix(path).unwrap())
652+
.unwrap();
653+
654+
let (socket, _) = listener.accept().unwrap();
655+
assert_common_flags(&socket, true);
656+
}
657+
634658
#[test]
635659
#[cfg(all(feature = "all", any(target_os = "android", target_os = "linux")))]
636660
#[ignore = "using VSOCK family requires optional kernel support (works when enabled)"]

0 commit comments

Comments
 (0)