Code change:
pub fn duplicate(&self) -> io::Result<FileDesc> { // We want to atomically duplicate this file descriptor and set the // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This <del> // flag, however, isn't supported on older Linux kernels (earlier than // 2.6.24). // // To detect this and ensure that CLOEXEC is still set, we // follow a strategy similar to musl [1] where if passing // F_DUPFD_CLOEXEC causes `fcntl` to return EINVAL it means it's not // supported (the third parameter, 0, is always valid), so we stop // trying that. // // Also note that Android doesn't have F_DUPFD_CLOEXEC, but get it to // resolve so we at least compile this. // // [1]: http://comments.gmane.org/gmane.linux.lib.musl.general/2963 #[cfg(any(target_os = "android", target_os = "haiku"))] use libc::F_DUPFD as F_DUPFD_CLOEXEC; #[cfg(not(any(target_os = "android", target_os = "haiku")))] use libc::F_DUPFD_CLOEXEC; let make_filedesc = |fd| { let fd = FileDesc::new(fd); fd.set_cloexec()?; Ok(fd) }; static TRY_CLOEXEC: AtomicBool = AtomicBool::new(!cfg!(target_os = "android")); let fd = self.raw(); if TRY_CLOEXEC.load(Ordering::Relaxed) { match cvt(unsafe { libc::fcntl(fd, F_DUPFD_CLOEXEC, 0) }) { // We *still* call the `set_cloexec` method as apparently some // linux kernel at some point stopped setting CLOEXEC even // though it reported doing so on F_DUPFD_CLOEXEC. Ok(fd) => { return Ok(if cfg!(target_os = "linux") { make_filedesc(fd)? } else { FileDesc::new(fd) }); } Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => { TRY_CLOEXEC.store(false, Ordering::Relaxed); } Err(e) => return Err(e), } } cvt(unsafe { libc::fcntl(fd, libc::F_DUPFD, 0) }).and_then(make_filedesc) </del> <ins> // is a POSIX flag that was added to Linux in 2.6.24. let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?; Ok(FileDesc::new(fd)) </ins> } }

Related discussion:
text: Good question! There are 6 workarounds in for older Linux versions (that I could find). Increasing the minimum version to 2.6.32 (aka 3rd Kernel LTS, aka RHEL 6) would fix 5 of them. Code links are inline: uses the flag with  (mentioned above, in 2.6.23) uses with  ( in 2.6.24, there is also the mention of a bug occuring on "some linux kernel at some point") uses  to atomically set the flag on the pipe fds ( in 2.6.27) uses with  ( in 2.6.27) uses  to permit use of ( in 2.6.28) ~ ( in 4.5, not fixed by this proposal)~ As you can see, the workarounds fixed by this proposal all have a similar flavor. Originally posted by in
Kernel updated in .
As noted, needs a much newer kernel 4.5, so we'll still need that fallback. But all the stuff should be ok to assume available now.
The new minimal version is 2.6.27 from what I can see, so "Socket::accept uses accept4(2) to permit use of SOCK_CLOEXEC" still needs a fallback, right?
The builder is using 2.6.32 headers, so I would call that our new minimum.
Ah right; I am actually not sure where I got the 27 from...
The title of suggested 2.6.27, but we went a little higher to match the actual distros in use.
I know this is ancient history, but do you recall the problem with ? You introduced that comment about "some kernel" in , and you were the last to update it in . If the problem kernels were before 2.6.32, then I'd like to clean that up now.
Just digging in kernel history, I did find one hiccup in , but that bug was introduced and resolved during the 3.7 development cycle, not in a release.
IIRC we just mirrored what musl did at the time, which looks like it : Looks like the original mailing list thread is gone and there's no comments in the musl source, and I don't recall what happened here. I suspect it would be safe to remove those workarounds and just assume works one the first try until someone says differently.