about summary refs log tree commit diff
path: root/src/libstd/sys/unix
diff options
context:
space:
mode:
authorAdrian Budau <budau.adi@gmail.com>2018-12-19 16:13:43 +0200
committerAdrian Budau <budau.adi@gmail.com>2018-12-20 13:22:31 +0200
commitcc53f4e9f48747d44718bb1b51e549437edae916 (patch)
treecb0894bd5157859ec8cef514fa3178085074b273 /src/libstd/sys/unix
parente7b4bc35e99ee3c5b2b42a1b8b3f9cd6eca1f0b2 (diff)
downloadrust-cc53f4e9f48747d44718bb1b51e549437edae916.tar.gz
rust-cc53f4e9f48747d44718bb1b51e549437edae916.zip
Fix pipe2 and accept4 on static linked executables on linux (like musl).
Diffstat (limited to 'src/libstd/sys/unix')
-rw-r--r--src/libstd/sys/unix/net.rs25
-rw-r--r--src/libstd/sys/unix/pipe.rs30
-rw-r--r--src/libstd/sys/unix/weak.rs52
3 files changed, 80 insertions, 27 deletions
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index d922be520d4..f30817e69ab 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -203,18 +203,21 @@ impl Socket {
         // 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
+            syscall! {
+                fn accept4(
+                    fd: c_int,
+                    addr: *mut sockaddr,
+                    addr_len: *mut socklen_t,
+                    flags: 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 res = cvt_r(|| unsafe {
+                accept4(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),
             }
         }
 
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 0a5dccdddda..24b2959a3fa 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -22,7 +22,7 @@ use sys::{cvt, cvt_r};
 pub struct AnonPipe(FileDesc);
 
 pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
-    weak! { fn pipe2(*mut c_int, c_int) -> c_int }
+    syscall! { fn pipe2(fds: *mut c_int, flags: c_int) -> c_int }
     static INVALID: AtomicBool = ATOMIC_BOOL_INIT;
 
     let mut fds = [0; 2];
@@ -39,22 +39,20 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
        !INVALID.load(Ordering::SeqCst)
     {
 
-        if let Some(pipe) = pipe2.get() {
-            // Note that despite calling a glibc function here we may still
-            // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
-            // emulate on older kernels, so if you happen to be running on
-            // an older kernel you may see `pipe2` as a symbol but still not
-            // see the syscall.
-            match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
-                Ok(_) => {
-                    return Ok((AnonPipe(FileDesc::new(fds[0])),
-                               AnonPipe(FileDesc::new(fds[1]))));
-                }
-                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
-                    INVALID.store(true, Ordering::SeqCst);
-                }
-                Err(e) => return Err(e),
+        // Note that despite calling a glibc function here we may still
+        // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
+        // emulate on older kernels, so if you happen to be running on
+        // an older kernel you may see `pipe2` as a symbol but still not
+        // see the syscall.
+        match cvt(unsafe { pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
+            Ok(_) => {
+                return Ok((AnonPipe(FileDesc::new(fds[0])),
+                            AnonPipe(FileDesc::new(fds[1]))));
+            }
+            Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
+                INVALID.store(true, Ordering::SeqCst);
             }
+            Err(e) => return Err(e),
         }
     }
     cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;
diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs
index 18944be58ee..3b73e3b7c50 100644
--- a/src/libstd/sys/unix/weak.rs
+++ b/src/libstd/sys/unix/weak.rs
@@ -77,3 +77,55 @@ unsafe fn fetch(name: &str) -> usize {
     };
     libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
 }
+
+#[cfg(not(target_os = "linux"))]
+macro_rules! syscall {
+    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+        unsafe fn $name($($arg_name: $t),*) -> $ret {
+            use libc;
+
+            weak! { fn $name($($t),*) -> $ret }
+
+            if let Some(fun) = $name.get() {
+                fun($($arg_name),*)
+            } else {
+                libc::ENOSYS
+            }
+        }
+    )
+}
+
+#[cfg(target_os = "linux")]
+macro_rules! syscall {
+    (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+        unsafe fn $name($($arg_name:$t),*) -> $ret {
+            // This like a hack, but concat_idents only accepts idents
+            // (not paths).
+            use libc::*;
+
+            syscall(
+                concat_idents!(SYS_, $name),
+                $(::sys::weak::SyscallParam::to_param($arg_name)),*
+            ) as $ret
+        }
+    )
+}
+
+#[cfg(target_os = "linux")]
+pub trait SyscallParam {
+    fn to_param(self) -> libc::c_long;
+}
+
+#[cfg(target_os = "linux")]
+impl SyscallParam for libc::c_int {
+    fn to_param(self) -> libc::c_long {
+        self as libc::c_long
+    }
+}
+
+#[cfg(target_os = "linux")]
+impl<T> SyscallParam for *mut T {
+    fn to_param(self) -> libc::c_long {
+        unsafe { mem::transmute(self) }
+    }
+}