Skip to content

Commit 05cc464

Browse files
committed
Auto merge of #27980 - tbu-:pr_cloexec_dup, r=alexcrichton
Still needs values of F_DUPFD_CLOEXEC on other OSs. For Bitrig, NetBSD and OpenBSD the constant was incorrectly in posix01, when it's actually posix08. In order to maintain backwards-compatiblity, the constant was only copied, not moved. cc #24237
2 parents 811868e + 1f81ef4 commit 05cc464

File tree

2 files changed

+31
-6
lines changed

2 files changed

+31
-6
lines changed

src/liblibc/lib.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -3614,6 +3614,7 @@ pub mod consts {
36143614
pub mod posix08 {
36153615
use types::os::arch::c95::c_int;
36163616
pub const O_CLOEXEC: c_int = 0x80000;
3617+
pub const F_DUPFD_CLOEXEC: c_int = 1030;
36173618
}
36183619
#[cfg(any(target_arch = "arm",
36193620
target_arch = "aarch64",
@@ -4285,11 +4286,13 @@ pub mod consts {
42854286
pub mod posix08 {
42864287
use types::os::arch::c95::c_int;
42874288
pub const O_CLOEXEC: c_int = 0x100000;
4289+
pub const F_DUPFD_CLOEXEC: c_int = 17;
42884290
}
42894291
#[cfg(target_os = "dragonfly")]
42904292
pub mod posix08 {
42914293
use types::os::arch::c95::c_int;
42924294
pub const O_CLOEXEC: c_int = 0x20000;
4295+
pub const F_DUPFD_CLOEXEC: c_int = 17;
42934296
}
42944297
pub mod bsd44 {
42954298
use types::os::arch::c95::c_int;
@@ -4657,7 +4660,6 @@ pub mod consts {
46574660
pub const F_GETLK : c_int = 7;
46584661
pub const F_SETLK : c_int = 8;
46594662
pub const F_SETLKW : c_int = 9;
4660-
pub const F_DUPFD_CLOEXEC : c_int = 10;
46614663

46624664
pub const SIGTRAP : c_int = 5;
46634665
pub const SIG_IGN: size_t = 1;
@@ -4739,11 +4741,13 @@ pub mod consts {
47394741
pub mod posix08 {
47404742
use types::os::arch::c95::c_int;
47414743
pub const O_CLOEXEC: c_int = 0x10000;
4744+
pub const F_DUPFD_CLOEXEC: c_int = 10;
47424745
}
47434746
#[cfg(target_os = "netbsd")]
47444747
pub mod posix08 {
47454748
use types::os::arch::c95::c_int;
47464749
pub const O_CLOEXEC: c_int = 0x400000;
4750+
pub const F_DUPFD_CLOEXEC: c_int = 12;
47474751
}
47484752
pub mod bsd44 {
47494753
use types::os::arch::c95::c_int;
@@ -5186,6 +5190,7 @@ pub mod consts {
51865190
pub mod posix08 {
51875191
use types::os::arch::c95::c_int;
51885192
pub const O_CLOEXEC: c_int = 0x1000000;
5193+
pub const F_DUPFD_CLOEXEC: c_int = 67;
51895194
}
51905195
pub mod bsd44 {
51915196
use types::os::arch::c95::c_int;

src/libstd/sys/unix/net.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ use prelude::v1::*;
1313
use ffi::CStr;
1414
use io;
1515
use libc::{self, c_int, size_t};
16+
use net::SocketAddr;
1617
use str;
18+
use sync::atomic::{self, AtomicBool};
1719
use sys::c;
18-
use net::SocketAddr;
1920
use sys::fd::FileDesc;
2021
use sys_common::{AsInner, FromInner, IntoInner};
2122
use sys_common::net::{getsockopt, setsockopt};
@@ -66,10 +67,29 @@ impl Socket {
6667
}
6768

6869
pub fn duplicate(&self) -> io::Result<Socket> {
69-
let fd = try!(cvt(unsafe { libc::dup(self.0.raw()) }));
70-
let fd = FileDesc::new(fd);
71-
fd.set_cloexec();
72-
Ok(Socket(fd))
70+
use libc::funcs::posix88::fcntl::fcntl;
71+
let make_socket = |fd| {
72+
let fd = FileDesc::new(fd);
73+
fd.set_cloexec();
74+
Socket(fd)
75+
};
76+
static EMULATE_F_DUPFD_CLOEXEC: AtomicBool = AtomicBool::new(false);
77+
if !EMULATE_F_DUPFD_CLOEXEC.load(atomic::Ordering::Relaxed) {
78+
match cvt(unsafe { fcntl(self.0.raw(), libc::F_DUPFD_CLOEXEC, 0) }) {
79+
// `EINVAL` can only be returned on two occasions: Invalid
80+
// command (second parameter) or invalid third parameter. 0 is
81+
// always a valid third parameter, so it must be the second
82+
// parameter.
83+
//
84+
// Store the result in a global variable so we don't try each
85+
// syscall twice.
86+
Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => {
87+
EMULATE_F_DUPFD_CLOEXEC.store(true, atomic::Ordering::Relaxed);
88+
}
89+
res => return res.map(make_socket),
90+
}
91+
}
92+
cvt(unsafe { fcntl(self.0.raw(), libc::F_DUPFD, 0) }).map(make_socket)
7393
}
7494

7595
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {

0 commit comments

Comments
 (0)