about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorAnders Kaseorg <andersk@mit.edu>2015-03-23 00:58:19 -0400
committerAnders Kaseorg <andersk@mit.edu>2015-03-23 01:05:05 -0400
commit0090e01f08f7ed564a62fb3cd2e3b652317d39d7 (patch)
tree7dc172dd099389d20ca227c6ee52a313151b9fc7 /src/libstd/sys
parentb0aad7dd4fad8d7e2e2f877a511a637258949597 (diff)
downloadrust-0090e01f08f7ed564a62fb3cd2e3b652317d39d7.tar.gz
rust-0090e01f08f7ed564a62fb3cd2e3b652317d39d7.zip
Get __pthread_get_minstack at runtime with dlsym
Linking __pthread_get_minstack, even weakly, was causing Debian’s
dpkg-shlibdeps to detect an unnecessarily strict versioned dependency
on libc6.

Closes #23628.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/unix/thread.rs35
1 files changed, 23 insertions, 12 deletions
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
index c5f07c6c75a..1d3cb43465b 100644
--- a/src/libstd/sys/unix/thread.rs
+++ b/src/libstd/sys/unix/thread.rs
@@ -13,12 +13,14 @@
 use core::prelude::*;
 
 use cmp;
+use dynamic_lib::DynamicLibrary;
 use ffi::CString;
 use io;
 use libc::consts::os::posix01::PTHREAD_STACK_MIN;
 use libc;
 use mem;
 use ptr;
+use sync::{Once, ONCE_INIT};
 use sys::os;
 use thunk::Thunk;
 use time::Duration;
@@ -314,21 +316,30 @@ pub fn sleep(dur: Duration) {
 // is created in an application with big thread-local storage requirements.
 // See #6233 for rationale and details.
 //
-// Link weakly to the symbol for compatibility with older versions of glibc.
-// Assumes that we've been dynamically linked to libpthread but that is
-// currently always the case.  Note that you need to check that the symbol
-// is non-null before calling it!
+// Use dlsym to get the symbol value at runtime, for compatibility
+// with older versions of glibc.  Assumes that we've been dynamically
+// linked to libpthread but that is currently always the case.  We
+// previously used weak linkage (under the same assumption), but that
+// caused Debian to detect an unnecessarily strict versioned
+// dependency on libc6 (#23628).
 #[cfg(target_os = "linux")]
 fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
     type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
-    extern {
-        #[linkage = "extern_weak"]
-        static __pthread_get_minstack: *const ();
-    }
-    if __pthread_get_minstack.is_null() {
-        PTHREAD_STACK_MIN
-    } else {
-        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
+    static INIT: Once = ONCE_INIT;
+    static mut __pthread_get_minstack: Option<F> = None;
+
+    INIT.call_once(|| {
+        let lib = DynamicLibrary::open(None).unwrap();
+        unsafe {
+            if let Ok(f) = lib.symbol("__pthread_get_minstack") {
+                __pthread_get_minstack = Some(mem::transmute::<*const (), F>(f));
+            }
+        }
+    });
+
+    match unsafe { __pthread_get_minstack } {
+        None => PTHREAD_STACK_MIN,
+        Some(f) => unsafe { f(attr) },
     }
 }