From 6f6e261e20fd1a770cb3477205c192dd158897f8 Mon Sep 17 00:00:00 2001 From: Mathieu Poumeyrol Date: Mon, 12 Sep 2016 21:38:28 +0200 Subject: [PATCH 1/3] set SO_NOSIGPIPE on apple platforms --- src/libstd/sys/unix/net.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index ec7ccdf5894fd..ad287bbec3889 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -33,6 +33,14 @@ use libc::SOCK_CLOEXEC; #[cfg(not(target_os = "linux"))] const SOCK_CLOEXEC: c_int = 0; +// Another conditional contant for name resolution: Macos et iOS use +// SO_NOSIGPIPE as a setsockopt flag to disable SIGPIPE emission on socket. +// Other platforms do otherwise. +#[cfg(target_vendor = "apple")] +use libc::SO_NOSIGPIPE; +#[cfg(not(target_vendor = "apple"))] +const SO_NOSIGPIPE: c_int = 0; + pub struct Socket(FileDesc); pub fn init() {} @@ -81,7 +89,11 @@ impl Socket { let fd = cvt(libc::socket(fam, ty, 0))?; let fd = FileDesc::new(fd); fd.set_cloexec()?; - Ok(Socket(fd)) + let socket = Socket(fd); + if cfg!(target_vendor = "apple") { + setsockopt(&socket, libc::SOL_SOCKET, SO_NOSIGPIPE, 1)?; + } + Ok(socket) } } From ed5e5428192f6f72afcb4becc3d78a18133613df Mon Sep 17 00:00:00 2001 From: Mathieu Poumeyrol Date: Tue, 27 Sep 2016 10:16:49 -0400 Subject: [PATCH 2/3] MSG_NOSIGNAL on linux --- src/libstd/sys/common/net.rs | 14 +++++++++++--- src/libstd/sys/unix/ext/net.rs | 8 +++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 18280e497db1d..d0d387c6ed9b9 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -42,6 +42,11 @@ use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; target_os = "solaris", target_os = "haiku")))] use sys::net::netc::IPV6_DROP_MEMBERSHIP; +#[cfg(target_os = "linux")] +const MSG_NOSIGNAL: c_int = 0x4000; +#[cfg(not(target_os = "linux"))] +const MSG_NOSIGNAL: c_int = 0x0; // unused dummy value + //////////////////////////////////////////////////////////////////////////////// // sockaddr and misc bindings //////////////////////////////////////////////////////////////////////////////// @@ -221,11 +226,12 @@ impl TcpStream { pub fn write(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let ret = cvt(unsafe { c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, - 0) + flags) })?; Ok(ret as usize) } @@ -446,10 +452,11 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; let (dstp, dstlen) = dst.into_inner(); + let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let ret = cvt(unsafe { c::sendto(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, - 0, dstp, dstlen) + flags, dstp, dstlen) })?; Ok(ret as usize) } @@ -569,11 +576,12 @@ impl UdpSocket { pub fn send(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; + let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let ret = cvt(unsafe { c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, - 0) + flags) })?; Ok(ret as usize) } diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index 3f93fce193561..f2e40714b469f 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -28,6 +28,11 @@ use sys::cvt; use sys::net::Socket; use sys_common::{AsInner, FromInner, IntoInner}; +#[cfg(target_os = "linux")] +const MSG_NOSIGNAL: libc::c_int = 0x4000; +#[cfg(not(target_os = "linux"))] +const MSG_NOSIGNAL: libc::c_int = 0x0; // unused dummy value + fn sun_path_offset() -> usize { unsafe { // Work with an actual instance of the type since using a null pointer is UB @@ -686,11 +691,12 @@ impl UnixDatagram { fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result { unsafe { let (addr, len) = sockaddr_un(path)?; + let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let count = cvt(libc::sendto(*d.0.as_inner(), buf.as_ptr() as *const _, buf.len(), - 0, + flags, &addr as *const _ as *const _, len))?; Ok(count as usize) From 5980d5bfddb8f1e92cee7f9a156c4758615bee4b Mon Sep 17 00:00:00 2001 From: Mathieu Poumeyrol Date: Wed, 28 Sep 2016 14:06:34 +0200 Subject: [PATCH 3/3] use MSG_NOSIGNAL from liblibc --- src/liblibc | 2 +- src/libstd/sys/common/net.rs | 11 ++++------- src/libstd/sys/unix/ext/net.rs | 5 ++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/liblibc b/src/liblibc index eb708c020826a..b474785561d58 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit eb708c020826a8d792a5a5275be147aabe47fe24 +Subproject commit b474785561d58efbd27add9d22339dcabad742ad diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index d0d387c6ed9b9..2599bb660e813 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -43,7 +43,7 @@ use sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; use sys::net::netc::IPV6_DROP_MEMBERSHIP; #[cfg(target_os = "linux")] -const MSG_NOSIGNAL: c_int = 0x4000; +use libc::MSG_NOSIGNAL; #[cfg(not(target_os = "linux"))] const MSG_NOSIGNAL: c_int = 0x0; // unused dummy value @@ -226,12 +226,11 @@ impl TcpStream { pub fn write(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; - let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let ret = cvt(unsafe { c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, - flags) + MSG_NOSIGNAL) })?; Ok(ret as usize) } @@ -452,11 +451,10 @@ impl UdpSocket { pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; let (dstp, dstlen) = dst.into_inner(); - let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let ret = cvt(unsafe { c::sendto(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, - flags, dstp, dstlen) + MSG_NOSIGNAL, dstp, dstlen) })?; Ok(ret as usize) } @@ -576,12 +574,11 @@ impl UdpSocket { pub fn send(&self, buf: &[u8]) -> io::Result { let len = cmp::min(buf.len(), ::max_value() as usize) as wrlen_t; - let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let ret = cvt(unsafe { c::send(*self.inner.as_inner(), buf.as_ptr() as *const c_void, len, - flags) + MSG_NOSIGNAL) })?; Ok(ret as usize) } diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs index f2e40714b469f..03ff8d9787f95 100644 --- a/src/libstd/sys/unix/ext/net.rs +++ b/src/libstd/sys/unix/ext/net.rs @@ -29,7 +29,7 @@ use sys::net::Socket; use sys_common::{AsInner, FromInner, IntoInner}; #[cfg(target_os = "linux")] -const MSG_NOSIGNAL: libc::c_int = 0x4000; +use libc::MSG_NOSIGNAL; #[cfg(not(target_os = "linux"))] const MSG_NOSIGNAL: libc::c_int = 0x0; // unused dummy value @@ -691,12 +691,11 @@ impl UnixDatagram { fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result { unsafe { let (addr, len) = sockaddr_un(path)?; - let flags = if cfg!(target_os = "linux") { MSG_NOSIGNAL } else { 0 }; let count = cvt(libc::sendto(*d.0.as_inner(), buf.as_ptr() as *const _, buf.len(), - flags, + MSG_NOSIGNAL, &addr as *const _ as *const _, len))?; Ok(count as usize)