about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-03 07:46:53 -0700
committerbors <bors@rust-lang.org>2013-08-03 07:46:53 -0700
commit34101d2320583a0a95ab3afc4c2b6b75dadb5cd7 (patch)
tree3326bcf9c1752689fd5c659c264cf73af2a58ada /src/libstd
parent6be014d23c178a69a5ce4b709cb3497a1e81a412 (diff)
parent2001cc043b7c20af1f72b9c39e61070fd1c639f6 (diff)
downloadrust-34101d2320583a0a95ab3afc4c2b6b75dadb5cd7.tar.gz
rust-34101d2320583a0a95ab3afc4c2b6b75dadb5cd7.zip
auto merge of #8213 : kballard/rust/fd-limit, r=brson
Revert the workaround 49b72bd and instead bump the fd limit on OS X.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/rt/test.rs87
1 files changed, 83 insertions, 4 deletions
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
index 1ed0703de4d..66ae085b1a0 100644
--- a/src/libstd/rt/test.rs
+++ b/src/libstd/rt/test.rs
@@ -63,6 +63,81 @@ pub fn run_in_newsched_task_core(f: ~fn()) {
     sched.bootstrap(task);
 }
 
+#[cfg(target_os="macos")]
+#[allow(non_camel_case_types)]
+mod darwin_fd_limit {
+    /*!
+     * darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the
+     * rlimit maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low
+     * for our multithreaded scheduler testing, depending on the number of cores available.
+     *
+     * This fixes issue #7772.
+     */
+
+    use libc;
+    type rlim_t = libc::uint64_t;
+    struct rlimit {
+        rlim_cur: rlim_t,
+        rlim_max: rlim_t
+    }
+    #[nolink]
+    extern {
+        // name probably doesn't need to be mut, but the C function doesn't specify const
+        fn sysctl(name: *mut libc::c_int, namelen: libc::c_uint,
+                  oldp: *mut libc::c_void, oldlenp: *mut libc::size_t,
+                  newp: *mut libc::c_void, newlen: libc::size_t) -> libc::c_int;
+        fn getrlimit(resource: libc::c_int, rlp: *mut rlimit) -> libc::c_int;
+        fn setrlimit(resource: libc::c_int, rlp: *rlimit) -> libc::c_int;
+    }
+    static CTL_KERN: libc::c_int = 1;
+    static KERN_MAXFILESPERPROC: libc::c_int = 29;
+    static RLIMIT_NOFILE: libc::c_int = 8;
+
+    pub unsafe fn raise_fd_limit() {
+        // The strategy here is to fetch the current resource limits, read the kern.maxfilesperproc
+        // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
+        use ptr::{to_unsafe_ptr, to_mut_unsafe_ptr, mut_null};
+        use sys::size_of_val;
+        use os::last_os_error;
+
+        // Fetch the kern.maxfilesperproc value
+        let mut mib: [libc::c_int, ..2] = [CTL_KERN, KERN_MAXFILESPERPROC];
+        let mut maxfiles: libc::c_int = 0;
+        let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
+        if sysctl(to_mut_unsafe_ptr(&mut mib[0]), 2,
+                  to_mut_unsafe_ptr(&mut maxfiles) as *mut libc::c_void,
+                  to_mut_unsafe_ptr(&mut size),
+                  mut_null(), 0) != 0 {
+            let err = last_os_error();
+            error!("raise_fd_limit: error calling sysctl: %s", err);
+            return;
+        }
+
+        // Fetch the current resource limits
+        let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
+        if getrlimit(RLIMIT_NOFILE, to_mut_unsafe_ptr(&mut rlim)) != 0 {
+            let err = last_os_error();
+            error!("raise_fd_limit: error calling getrlimit: %s", err);
+            return;
+        }
+
+        // Bump the soft limit to the smaller of kern.maxfilesperproc and the hard limit
+        rlim.rlim_cur = ::cmp::min(maxfiles as rlim_t, rlim.rlim_max);
+
+        // Set our newly-increased resource limit
+        if setrlimit(RLIMIT_NOFILE, to_unsafe_ptr(&rlim)) != 0 {
+            let err = last_os_error();
+            error!("raise_fd_limit: error calling setrlimit: %s", err);
+            return;
+        }
+    }
+}
+
+#[cfg(not(target_os="macos"))]
+mod darwin_fd_limit {
+    pub unsafe fn raise_fd_limit() {}
+}
+
 /// Create more than one scheduler and run a function in a task
 /// in one of the schedulers. The schedulers will stay alive
 /// until the function `f` returns.
@@ -70,6 +145,10 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
     use os;
     use from_str::FromStr;
     use rt::sched::Shutdown;
+    use rt::util;
+
+    // Bump the fd limit on OS X. See darwin_fd_limit for an explanation.
+    unsafe { darwin_fd_limit::raise_fd_limit() }
 
     let f = Cell::new(f);
 
@@ -77,10 +156,10 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
         let nthreads = match os::getenv("RUST_RT_TEST_THREADS") {
             Some(nstr) => FromStr::from_str(nstr).get(),
             None => {
-                // A reasonable number of threads for testing
-                // multithreading. NB: It's easy to exhaust OS X's
-                // low maximum fd limit by setting this too high (#7772)
-                4
+                // Using more threads than cores in test code
+                // to force the OS to preempt them frequently.
+                // Assuming that this help stress test concurrent types.
+                util::num_cpus() * 2
             }
         };