Skip to content

Commit 72cebbc

Browse files
bors[bot]Bryant Mairs
and
Bryant Mairs
committed
Merge #907
907: Remove emulation of FD_CLOEXEC/O_NONBLOCK r=asomers a=Susurrus Rather than using the native implementation of these constants on supported platforms, the native implementation was instead emulated. This was also hidden from the user even though this could result in data races and the functionality being broken. Native functionality is, however, not support on macos/ios. Rather than enable this emulation solely for this platform, it should be removed as this is a dangerous abstraction. This is a replacement for #863. There is much previous discussion there which I recommend you read to familiarize yourself with this decision. I'm looking to push this through rather quickly as it's the last thing blocking our next 0.11.0 release. cc @aomser @kristate Co-authored-by: Bryant Mairs <bryantmairs@google.com>
2 parents badb451 + 7e870c0 commit 72cebbc

File tree

3 files changed

+88
-98
lines changed

3 files changed

+88
-98
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
5151
([#892](https://github.com/nix-rust/nix/pull/892))
5252
- Remove `IFF_NOTRAILERS` on OpenBSD, as it has been removed in OpenBSD 6.3
5353
([#893](https://github.com/nix-rust/nix/pull/893))
54+
- Emulation of `FD_CLOEXEC` and `O_NONBLOCK` was removed from `socket()`, `accept4()`, and
55+
`socketpair()`.
56+
([#907](https://github.com/nix-rust/nix/pull/907))
5457

5558
### Fixed
5659
- Fixed possible panics when using `SigAction::flags` on Linux
@@ -68,6 +71,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
6871
([#872](https://github.com/nix-rust/nix/pull/872))
6972
- Removed `sys::aio::lio_listio`. Use `sys::aio::LioCb::listio` instead.
7073
([#872](https://github.com/nix-rust/nix/pull/872))
74+
- Removed emulated `accept4()` from macos, ios, and netbsd targets
75+
([#907](https://github.com/nix-rust/nix/pull/907))
7176

7277
## [0.10.0] 2018-01-26
7378

src/sys/socket/mod.rs

+21-98
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
44
use {Error, Result};
55
use errno::Errno;
6-
use features;
76
use libc::{self, c_void, c_int, socklen_t, size_t};
87
use std::{fmt, mem, ptr, slice};
98
use std::os::unix::io::RawFd;
@@ -692,87 +691,43 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
692691
///
693692
/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html)
694693
pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
695-
let mut ty = ty as c_int;
696694
let protocol = match protocol.into() {
697695
None => 0,
698696
Some(p) => p as c_int,
699697
};
700-
let feat_atomic = features::socket_atomic_cloexec();
701-
702-
if feat_atomic {
703-
ty |= flags.bits();
704-
}
705-
706-
// TODO: Check the kernel version
707-
let res = try!(Errno::result(unsafe { libc::socket(domain as c_int, ty, protocol) }));
708-
709-
#[cfg(any(target_os = "android",
710-
target_os = "dragonfly",
711-
target_os = "freebsd",
712-
target_os = "linux",
713-
target_os = "netbsd",
714-
target_os = "openbsd"))]
715-
{
716-
use fcntl::{fcntl, FdFlag, OFlag};
717-
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
718698

719-
if !feat_atomic {
720-
if flags.contains(SockFlag::SOCK_CLOEXEC) {
721-
try!(fcntl(res, F_SETFD(FdFlag::FD_CLOEXEC)));
722-
}
699+
// SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
700+
// little easier to understand by separating it out. So we have to merge these bitfields
701+
// here.
702+
let mut ty = ty as c_int;
703+
ty |= flags.bits();
723704

724-
if flags.contains(SockFlag::SOCK_NONBLOCK) {
725-
try!(fcntl(res, F_SETFL(OFlag::O_NONBLOCK)));
726-
}
727-
}
728-
}
705+
let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
729706

730-
Ok(res)
707+
Errno::result(res)
731708
}
732709

733710
/// Create a pair of connected sockets
734711
///
735712
/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
736713
pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
737714
flags: SockFlag) -> Result<(RawFd, RawFd)> {
738-
let mut ty = ty as c_int;
739715
let protocol = match protocol.into() {
740716
None => 0,
741717
Some(p) => p as c_int,
742718
};
743-
let feat_atomic = features::socket_atomic_cloexec();
744719

745-
if feat_atomic {
746-
ty |= flags.bits();
747-
}
720+
// SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
721+
// little easier to understand by separating it out. So we have to merge these bitfields
722+
// here.
723+
let mut ty = ty as c_int;
724+
ty |= flags.bits();
725+
748726
let mut fds = [-1, -1];
749-
let res = unsafe {
750-
libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr())
751-
};
752-
try!(Errno::result(res));
753-
754-
#[cfg(any(target_os = "android",
755-
target_os = "dragonfly",
756-
target_os = "freebsd",
757-
target_os = "linux",
758-
target_os = "netbsd",
759-
target_os = "openbsd"))]
760-
{
761-
use fcntl::{fcntl, FdFlag, OFlag};
762-
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
763727

764-
if !feat_atomic {
765-
if flags.contains(SockFlag::SOCK_CLOEXEC) {
766-
try!(fcntl(fds[0], F_SETFD(FdFlag::FD_CLOEXEC)));
767-
try!(fcntl(fds[1], F_SETFD(FdFlag::FD_CLOEXEC)));
768-
}
728+
let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
729+
Errno::result(res)?;
769730

770-
if flags.contains(SockFlag::SOCK_NONBLOCK) {
771-
try!(fcntl(fds[0], F_SETFL(OFlag::O_NONBLOCK)));
772-
try!(fcntl(fds[1], F_SETFL(OFlag::O_NONBLOCK)));
773-
}
774-
}
775-
}
776731
Ok((fds[0], fds[1]))
777732
}
778733

@@ -809,46 +764,14 @@ pub fn accept(sockfd: RawFd) -> Result<RawFd> {
809764
/// Accept a connection on a socket
810765
///
811766
/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
767+
#[cfg(any(target_os = "android",
768+
target_os = "freebsd",
769+
target_os = "linux",
770+
target_os = "openbsd"))]
812771
pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
813-
accept4_polyfill(sockfd, flags)
814-
}
815-
816-
#[inline]
817-
fn accept4_polyfill(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
818-
let res = try!(Errno::result(unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) }));
819-
820-
#[cfg(any(target_os = "android",
821-
target_os = "dragonfly",
822-
target_os = "freebsd",
823-
target_os = "linux",
824-
target_os = "netbsd",
825-
target_os = "openbsd"))]
826-
{
827-
use fcntl::{fcntl, FdFlag, OFlag};
828-
use fcntl::FcntlArg::{F_SETFD, F_SETFL};
829-
830-
if flags.contains(SockFlag::SOCK_CLOEXEC) {
831-
try!(fcntl(res, F_SETFD(FdFlag::FD_CLOEXEC)));
832-
}
833-
834-
if flags.contains(SockFlag::SOCK_NONBLOCK) {
835-
try!(fcntl(res, F_SETFL(OFlag::O_NONBLOCK)));
836-
}
837-
}
838-
839-
// Disable unused variable warning on some platforms
840-
#[cfg(not(any(target_os = "android",
841-
target_os = "dragonfly",
842-
target_os = "freebsd",
843-
target_os = "linux",
844-
target_os = "netbsd",
845-
target_os = "openbsd")))]
846-
{
847-
let _ = flags;
848-
}
772+
let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
849773

850-
851-
Ok(res)
774+
Errno::result(res)
852775
}
853776

854777
/// Initiate a connection on a socket

test/sys/test_socket.rs

+62
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,65 @@ pub fn test_syscontrol() {
255255
// requires root privileges
256256
// connect(fd, &sockaddr).expect("connect failed");
257257
}
258+
259+
/// Test non-blocking mode on new sockets via SockFlag::O_NONBLOCK
260+
#[cfg(any(target_os = "android",
261+
target_os = "dragonfly",
262+
target_os = "freebsd",
263+
target_os = "linux",
264+
target_os = "netbsd",
265+
target_os = "openbsd"))]
266+
#[test]
267+
pub fn test_sockflag_nonblock() {
268+
use libc;
269+
use nix::fcntl::{fcntl};
270+
use nix::fcntl::FcntlArg::{F_GETFL};
271+
use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
272+
273+
/* first, try without SockFlag::SOCK_NONBLOCK */
274+
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
275+
.expect("socket failed");
276+
277+
let fcntl_res = fcntl(sock, F_GETFL).expect("fcntl failed");
278+
279+
assert!(fcntl_res & libc::O_NONBLOCK == 0);
280+
281+
/* next, try with SockFlag::SOCK_NONBLOCK */
282+
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::SOCK_NONBLOCK, None)
283+
.expect("socket failed");
284+
285+
let fcntl_res = fcntl(sock, F_GETFL).expect("fcntl failed");
286+
287+
assert!(fcntl_res & libc::O_NONBLOCK == libc::O_NONBLOCK);
288+
}
289+
290+
/// Test close-on-exec on new sockets via SockFlag::SOCK_CLOEXEC
291+
#[cfg(any(target_os = "android",
292+
target_os = "dragonfly",
293+
target_os = "freebsd",
294+
target_os = "linux",
295+
target_os = "netbsd",
296+
target_os = "openbsd"))]
297+
#[test]
298+
pub fn test_sockflag_cloexec() {
299+
use libc;
300+
use nix::fcntl::{fcntl};
301+
use nix::fcntl::FcntlArg::{F_GETFD};
302+
use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
303+
304+
/* first, test without SockFlag::SOCK_CLOEXEC */
305+
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
306+
.expect("socket failed");
307+
308+
let fcntl_res = fcntl(sock, F_GETFD).expect("fcntl failed");
309+
310+
assert!(fcntl_res & libc::FD_CLOEXEC == 0);
311+
312+
/* next, test without SockFlag::SOCK_CLOEXEC */
313+
let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::SOCK_CLOEXEC, None)
314+
.expect("socket failed");
315+
316+
let fcntl_res = fcntl(sock, F_GETFD).expect("fcntl failed");
317+
318+
assert!(fcntl_res & libc::FD_CLOEXEC == libc::FD_CLOEXEC);
319+
}

0 commit comments

Comments
 (0)