about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
m---------src/liblibc0
-rw-r--r--src/libstd/sys/unix/mod.rs36
-rw-r--r--src/libstd/sys/unix/process.rs2
-rw-r--r--src/libstd/sys/unix/weak.rs8
4 files changed, 37 insertions, 9 deletions
diff --git a/src/liblibc b/src/liblibc
-Subproject 2278a549559c38872b4338cb002ecc2a80d860d
+Subproject 7265c17d1845354f979a39b4ceb3a6934025b2a
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index c332d6035ee..f8b2d4dd232 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -85,12 +85,46 @@ pub fn init() {
 
     #[cfg(not(target_os = "nacl"))]
     unsafe fn reset_sigpipe() {
-        assert!(libc::signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
+        assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
     }
     #[cfg(target_os = "nacl")]
     unsafe fn reset_sigpipe() {}
 }
 
+// Currently the minimum supported Android version of the standard library is
+// API level 18 (android-18). Back in those days [1] the `signal` function was
+// just an inline wrapper around `bsd_signal`, but starting in API level
+// android-20 the `signal` symbols was introduced [2]. Finally, in android-21
+// the API `bsd_signal` was removed [3].
+//
+// Basically this means that if we want to be binary compatible with multiple
+// Android releases (oldest being 18 and newest being 21) then we need to check
+// for both symbols and not actually link against either.
+//
+// Note that if we're not on android we just link against the `android` symbol
+// itself.
+//
+// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
+//                                       /android-18/arch-arm/usr/include/signal.h
+// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental
+//                                       /platforms/android-20/arch-arm
+//                                       /usr/include/signal.h
+// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms
+//                                       /android-21/arch-arm/usr/include/signal.h
+#[cfg(target_os = "android")]
+unsafe fn signal(signum: libc::c_int,
+                 handler: libc::sighandler_t) -> libc::sighandler_t {
+    weak!(fn signal(libc::c_int, libc::sighandler_t) -> libc::sighandler_t);
+    weak!(fn bsd_signal(libc::c_int, libc::sighandler_t) -> libc::sighandler_t);
+
+    let f = signal.get().or_else(|| bsd_signal.get());
+    let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
+    f(signum, handler)
+}
+
+#[cfg(not(target_os = "android"))]
+pub use libc::signal;
+
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno as libc::c_int {
         libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 6f56f3ade06..270c2096b2c 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -393,7 +393,7 @@ impl Command {
             t!(cvt(libc::sigemptyset(&mut set)));
             t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
                                          ptr::null_mut())));
-            let ret = libc::signal(libc::SIGPIPE, libc::SIG_DFL);
+            let ret = super::signal(libc::SIGPIPE, libc::SIG_DFL);
             if ret == libc::SIG_ERR {
                 return io::Error::last_os_error()
             }
diff --git a/src/libstd/sys/unix/weak.rs b/src/libstd/sys/unix/weak.rs
index e6f85c08d12..99ab8741159 100644
--- a/src/libstd/sys/unix/weak.rs
+++ b/src/libstd/sys/unix/weak.rs
@@ -75,11 +75,5 @@ unsafe fn fetch(name: &str) -> usize {
         Ok(cstr) => cstr,
         Err(..) => return 0,
     };
-    let lib = libc::dlopen(0 as *const _, libc::RTLD_LAZY);
-    if lib.is_null() {
-        return 0
-    }
-    let ret = libc::dlsym(lib, name.as_ptr()) as usize;
-    libc::dlclose(lib);
-    return ret
+    libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
 }