Change:
After lands we will be setting on all file descriptors on unix in the standard library. Currently we do so in a nonatomic fashion, however, so it's possible to continue to leak file descriptors into children if a thread is concurrently forking. Many platforms have methods of creating file descriptors atomically, but many of the APIs are quite new and they need to be properly detected at runtime. For example, the current instances of that need to be migrated are listed below. A reminder of our minimum platform requirements are linux 2.6.18 and OSX 10.7. [x] - this should specify the flag. This flag was in linux 2.6.23 and appears to exist on OSX 10.7. [x] - this should be specify the flag in the argument (second). This flag was only in linux 2.6.27 and does not exist on OSX. [x] - this should be replaced with a call to . This system call was only in linux 2.6.28 and does not exist on OSX. [x] - this should be replaced with (linux 2.6.27, not on OSX) or (linux 2.6.24, appears to exist on OSX 10.7). [x] - this could be replaced with on linux 2.6.27 and perhaps on OSX (not confirmed). The hard part about this bug is figuring out if it's possible to avoid compile-time detection of these functions (and instead rely on runtime detection).
cc
I know this is closed, but I just have to comment on how well thought out and organised the original description was - how clearly the problem is captured and then it's solution tracked. Well done everyone.

Discussion:
pub use consts::os::c95::*; pub use consts::os::posix88::*; pub use consts::os::posix01::*; <ins> pub use consts::os::posix08::*; </ins> pub use consts::os::bsd44::*; pub use consts::os::extra::*;

pub const RUSAGE_THREAD: c_int = 1; } pub mod posix08 { <ins> use types::os::arch::c95::c_int; pub const O_CLOEXEC: c_int = 0x80000; </ins> } #[cfg(any(target_arch = "arm", target_arch = "aarch64",

pub const RUSAGE_CHILDREN: c_int = -1; pub const RUSAGE_THREAD: c_int = 1; } <ins> #[cfg(target_os = "freebsd")] </ins> pub mod posix08 { <ins> use types::os::arch::c95::c_int; pub const O_CLOEXEC: c_int = 0x100000; } #[cfg(target_os = "dragonfly")] pub mod posix08 { use types::os::arch::c95::c_int; pub const O_CLOEXEC: c_int = 0x20000; </ins> } pub mod bsd44 { use types::os::arch::c95::c_int;

pub const RUSAGE_CHILDREN: c_int = -1; pub const RUSAGE_THREAD: c_int = 1; } <ins> #[cfg(any(target_os = "bitrig", target_os = "openbsd"))] </ins> pub mod posix08 { <ins> use types::os::arch::c95::c_int; pub const O_CLOEXEC: c_int = 0x10000; } #[cfg(target_os = "netbsd")] pub mod posix08 { use types::os::arch::c95::c_int; pub const O_CLOEXEC: c_int = 0x400000; </ins> } pub mod bsd44 { use types::os::arch::c95::c_int;

pub const RUSAGE_THREAD: c_int = 1; } pub mod posix08 { <ins> use types::os::arch::c95::c_int; pub const O_CLOEXEC: c_int = 0x1000000; </ins> } pub mod bsd44 { use types::os::arch::c95::c_int;

impl OpenOptions { pub fn new() -> OpenOptions { OpenOptions { <del> flags: 0, </del> <ins> flags: libc::O_CLOEXEC, </ins> read: false, write: false, mode: 0o666,

libc::open(path.as_ptr(), flags, opts.mode) })); let fd = FileDesc::new(fd); <ins> // Even though we open with the O_CLOEXEC flag, still set CLOEXEC here, // in case the open flag is not supported (it's just ignored by the OS // in that case). </ins> fd.set_cloexec(); Ok(File(fd)) }