diff options
| author | Michał Łowicki <mlowicki@gmail.com> | 2025-04-18 10:38:17 +0200 |
|---|---|---|
| committer | Michał Łowicki <michal.lowicki@datadoghq.com> | 2025-06-16 09:15:17 +0200 |
| commit | 426ab142507fca8704d934da556f1c96b0fd61b2 (patch) | |
| tree | 971db0ea8dc6503539410cda2de05189570c6264 | |
| parent | ed44c0e3b3a4f90c464361ec6892c1d42c15ea8f (diff) | |
| download | rust-426ab142507fca8704d934da556f1c96b0fd61b2.tar.gz rust-426ab142507fca8704d934da556f1c96b0fd61b2.zip | |
Set MSG_NOSIGNAL for UnixSteam
https://github.com/rust-lang/rust/issues/139956 fix
| -rw-r--r-- | library/std/src/net/tcp.rs | 6 | ||||
| -rw-r--r-- | library/std/src/os/unix/net/stream.rs | 23 | ||||
| -rw-r--r-- | library/std/src/sys/net/connection/socket/unix.rs | 8 |
3 files changed, 36 insertions, 1 deletions
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs index 6a951426407..10685b49319 100644 --- a/library/std/src/net/tcp.rs +++ b/library/std/src/net/tcp.rs @@ -53,6 +53,12 @@ use crate::time::Duration; /// Ok(()) /// } // the stream is closed here /// ``` +/// +/// # Platform-specific Behavior +/// +/// On Unix, writes to the underlying socket in `SOCK_STREAM` mode are made with +/// `MSG_NOSIGNAL` flag. This suppresses the emission of the `SIGPIPE` signal when writing +/// to disconnected socket. In some cases, getting a `SIGPIPE` would trigger process termination. #[stable(feature = "rust1", since = "1.0.0")] pub struct TcpStream(net_imp::TcpStream); diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 1bd3bab5e37..035768a6fab 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -1,3 +1,18 @@ +cfg_if::cfg_if! { + if #[cfg(any( + target_os = "linux", target_os = "android", + target_os = "hurd", + target_os = "dragonfly", target_os = "freebsd", + target_os = "openbsd", target_os = "netbsd", + target_os = "solaris", target_os = "illumos", + target_os = "haiku", target_os = "nto", + target_os = "cygwin"))] { + use libc::MSG_NOSIGNAL; + } else { + const MSG_NOSIGNAL: core::ffi::c_int = 0x0; + } +} + use super::{SocketAddr, sockaddr_un}; #[cfg(any(doc, target_os = "android", target_os = "linux"))] use super::{SocketAncillary, recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to}; @@ -41,6 +56,12 @@ use crate::time::Duration; /// Ok(()) /// } /// ``` +/// +/// # `SIGPIPE` +/// +/// Writes to the underlying socket in `SOCK_STREAM` mode are made with `MSG_NOSIGNAL` flag. +/// This suppresses the emission of the `SIGPIPE` signal when writing to disconnected socket. +/// In some cases getting a `SIGPIPE` would trigger process termination. #[stable(feature = "unix_socket", since = "1.10.0")] pub struct UnixStream(pub(super) Socket); @@ -633,7 +654,7 @@ impl io::Write for UnixStream { #[stable(feature = "unix_socket", since = "1.10.0")] impl<'a> io::Write for &'a UnixStream { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - self.0.write(buf) + self.0.send_with_flags(buf, MSG_NOSIGNAL) } fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { diff --git a/library/std/src/sys/net/connection/socket/unix.rs b/library/std/src/sys/net/connection/socket/unix.rs index b35d5d2aa84..b2a4961c3c5 100644 --- a/library/std/src/sys/net/connection/socket/unix.rs +++ b/library/std/src/sys/net/connection/socket/unix.rs @@ -281,6 +281,14 @@ impl Socket { self.0.duplicate().map(Socket) } + pub fn send_with_flags(&self, buf: &[u8], flags: c_int) -> io::Result<usize> { + let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t; + let ret = cvt(unsafe { + libc::send(self.as_raw_fd(), buf.as_ptr() as *const c_void, len, flags) + })?; + Ok(ret as usize) + } + fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { let ret = cvt(unsafe { libc::recv( |
