Skip to content

Commit 241a9d0

Browse files
committed
Auto merge of #32415 - alexcrichton:android-signal, r=alexcrichton
std: Fix linking against `signal` on Android 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
2 parents 57e5d43 + 9c462b8 commit 241a9d0

File tree

4 files changed

+38
-10
lines changed

4 files changed

+38
-10
lines changed

src/liblibc

Submodule liblibc updated 45 files

src/libstd/sys/unix/mod.rs

+35-1
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,46 @@ pub fn init() {
8585

8686
#[cfg(not(target_os = "nacl"))]
8787
unsafe fn reset_sigpipe() {
88-
assert!(libc::signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
88+
assert!(signal(libc::SIGPIPE, libc::SIG_IGN) != !0);
8989
}
9090
#[cfg(target_os = "nacl")]
9191
unsafe fn reset_sigpipe() {}
9292
}
9393

94+
// Currently the minimum supported Android version of the standard library is
95+
// API level 18 (android-18). Back in those days [1] the `signal` function was
96+
// just an inline wrapper around `bsd_signal`, but starting in API level
97+
// android-20 the `signal` symbols was introduced [2]. Finally, in android-21
98+
// the API `bsd_signal` was removed [3].
99+
//
100+
// Basically this means that if we want to be binary compatible with multiple
101+
// Android releases (oldest being 18 and newest being 21) then we need to check
102+
// for both symbols and not actually link against either.
103+
//
104+
// Note that if we're not on android we just link against the `android` symbol
105+
// itself.
106+
//
107+
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms
108+
// /android-18/arch-arm/usr/include/signal.h
109+
// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental
110+
// /platforms/android-20/arch-arm
111+
// /usr/include/signal.h
112+
// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms
113+
// /android-21/arch-arm/usr/include/signal.h
114+
#[cfg(target_os = "android")]
115+
unsafe fn signal(signum: libc::c_int,
116+
handler: libc::sighandler_t) -> libc::sighandler_t {
117+
weak!(fn signal(libc::c_int, libc::sighandler_t) -> libc::sighandler_t);
118+
weak!(fn bsd_signal(libc::c_int, libc::sighandler_t) -> libc::sighandler_t);
119+
120+
let f = signal.get().or_else(|| bsd_signal.get());
121+
let f = f.expect("neither `signal` nor `bsd_signal` symbols found");
122+
f(signum, handler)
123+
}
124+
125+
#[cfg(not(target_os = "android"))]
126+
pub use libc::signal;
127+
94128
pub fn decode_error_kind(errno: i32) -> ErrorKind {
95129
match errno as libc::c_int {
96130
libc::ECONNREFUSED => ErrorKind::ConnectionRefused,

src/libstd/sys/unix/process.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ impl Command {
393393
t!(cvt(libc::sigemptyset(&mut set)));
394394
t!(cvt(libc::pthread_sigmask(libc::SIG_SETMASK, &set,
395395
ptr::null_mut())));
396-
let ret = libc::signal(libc::SIGPIPE, libc::SIG_DFL);
396+
let ret = super::signal(libc::SIGPIPE, libc::SIG_DFL);
397397
if ret == libc::SIG_ERR {
398398
return io::Error::last_os_error()
399399
}

src/libstd/sys/unix/weak.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,5 @@ unsafe fn fetch(name: &str) -> usize {
7575
Ok(cstr) => cstr,
7676
Err(..) => return 0,
7777
};
78-
let lib = libc::dlopen(0 as *const _, libc::RTLD_LAZY);
79-
if lib.is_null() {
80-
return 0
81-
}
82-
let ret = libc::dlsym(lib, name.as_ptr()) as usize;
83-
libc::dlclose(lib);
84-
return ret
78+
libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
8579
}

0 commit comments

Comments
 (0)