about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstd/sys/unix/net.rs26
-rw-r--r--src/libstd/sys/unix/weak.rs6
2 files changed, 28 insertions, 4 deletions
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 728bc258c00..507cc0f4ea4 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -12,7 +12,7 @@ use prelude::v1::*;
 
 use ffi::CStr;
 use io;
-use libc::{self, c_int, size_t};
+use libc::{self, c_int, size_t, sockaddr, socklen_t};
 use net::{SocketAddr, Shutdown};
 use str;
 use sys::fd::FileDesc;
@@ -78,8 +78,28 @@ impl Socket {
         }
     }
 
-    pub fn accept(&self, storage: *mut libc::sockaddr,
-                  len: *mut libc::socklen_t) -> io::Result<Socket> {
+    pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t)
+                  -> io::Result<Socket> {
+        // Unfortunately the only known way right now to accept a socket and
+        // atomically set the CLOEXEC flag is to use the `accept4` syscall on
+        // Linux. This was added in 2.6.28, however, and because we support
+        // 2.6.18 we must detect this support dynamically.
+        if cfg!(target_os = "linux") {
+            weak! {
+                fn accept4(c_int, *mut sockaddr, *mut socklen_t, c_int) -> c_int
+            }
+            if let Some(accept) = accept4.get() {
+                let res = cvt_r(|| unsafe {
+                    accept(self.0.raw(), storage, len, SOCK_CLOEXEC)
+                });
+                match res {
+                    Ok(fd) => return Ok(Socket(FileDesc::new(fd))),
+                    Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {}
+                    Err(e) => return Err(e),
+                }
+            }
+        }
+
         let fd = try!(cvt_r(|| unsafe {
             libc::accept(self.0.raw(), storage, len)
         }));
diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs
index 2cbcd62f533..e6f85c08d12 100644
--- a/src/libstd/sys/unix/weak.rs
+++ b/src/libstd/sys/unix/weak.rs
@@ -61,7 +61,11 @@ impl<F> Weak<F> {
             if self.addr.load(Ordering::SeqCst) == 1 {
                 self.addr.store(fetch(self.name), Ordering::SeqCst);
             }
-            mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr)
+            if self.addr.load(Ordering::SeqCst) == 0 {
+                None
+            } else {
+                mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr)
+            }
         }
     }
 }