]> git.lizzy.rs Git - rust.git/commitdiff
std: Fix linking against `signal` on Android
authorAlex Crichton <alex@alexcrichton.com>
Mon, 21 Mar 2016 23:54:53 +0000 (16:54 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 5 Apr 2016 04:54:59 +0000 (21:54 -0700)
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.

This was first discovered in rust-lang/libc#236 with a fix proposed in
rust-lang/libc#237. I suspect that we'll want to accept rust-lang/libc#237 so
Rust crates at large continue to be compatible with newer releases of Android
and crates, like the standard library, that want to opt into older support can
continue to do so via similar means.

Closes rust-lang/libc#236

[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

src/liblibc
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/weak.rs

index 2278a549559c38872b4338cb002ecc2a80d860dc..7265c17d1845354f979a39b4ceb3a6934025b2ab 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2278a549559c38872b4338cb002ecc2a80d860dc
+Subproject commit 7265c17d1845354f979a39b4ceb3a6934025b2ab
index c332d6035ee8d8d789ccf681bbae8c754cdd55a8..f8b2d4dd23240bdcaf5f32fcbffe81357c46758d 100644 (file)
@@ -85,12 +85,46 @@ fn oom_handler() -> ! {
 
     #[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,
index 6f56f3ade065a482d9c36d676491cf5df0c21b61..270c2096b2c3b33aa34f3fca35e8fbd2fa600ec6 100644 (file)
@@ -393,7 +393,7 @@ macro_rules! t {
             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()
             }
index e6f85c08d1246cf06ee0f88ad9935b49cbf83262..99ab8741159e39075825b1a4e01fab4f2dea9cf1 100644 (file)
@@ -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
 }