From 98dc7b15afb7bcbbbb47d13a40ecf6dfdad0c9f9 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Fri, 9 Aug 2013 16:30:44 -0700 Subject: [PATCH] Try to fix mac valgrind bot by disabling thread-heavy activities. --- src/libstd/rt/comm.rs | 10 ++++++++++ src/libstd/rt/sched.rs | 2 ++ src/libstd/rt/test.rs | 14 +++++++++----- src/libstd/rt/util.rs | 26 +++++++++++++++++++++++++- src/libstd/run.rs | 9 +-------- src/libstd/unstable/mod.rs | 14 ++++++++++++++ 6 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 0cf223f302913..afd1192baf9dd 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -692,6 +692,7 @@ mod test { use rt::test::*; use cell::Cell; use iter::Times; + use rt::util; #[test] fn oneshot_single_thread_close_port_first() { @@ -840,6 +841,7 @@ mod test { #[test] fn oneshot_multi_thread_close_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do stress_factor().times { do run_in_newsched_task { let (port, chan) = oneshot::(); @@ -855,6 +857,7 @@ mod test { #[test] fn oneshot_multi_thread_send_close_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do stress_factor().times { do run_in_newsched_task { let (port, chan) = oneshot::(); @@ -875,6 +878,7 @@ mod test { #[test] fn oneshot_multi_thread_recv_close_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do stress_factor().times { do run_in_newsched_task { let (port, chan) = oneshot::(); @@ -901,6 +905,7 @@ mod test { #[test] fn oneshot_multi_thread_send_recv_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do stress_factor().times { do run_in_newsched_task { let (port, chan) = oneshot::<~int>(); @@ -920,6 +925,7 @@ mod test { #[test] fn stream_send_recv_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do stress_factor().times { do run_in_mt_newsched_task { let (port, chan) = stream::<~int>(); @@ -964,6 +970,7 @@ mod test { #[test] fn shared_chan_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do run_in_mt_newsched_task { let (port, chan) = stream(); let chan = SharedChan::new(chan); @@ -983,6 +990,7 @@ mod test { #[test] fn shared_port_stress() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do run_in_mt_newsched_task { // XXX: Removing these type annotations causes an ICE let (end_port, end_chan) = stream::<()>(); @@ -1063,6 +1071,8 @@ mod test { use rand; use rand::RngUtil; + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } + do run_in_mt_newsched_task { let (end_port, end_chan) = stream::<()>(); let end_chan = SharedChan::new(end_chan); diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index 990e1a4a3de99..20d6e7da2f946 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -754,6 +754,7 @@ mod test { use cell::Cell; use rt::thread::Thread; use rt::task::{Task, Sched}; + use rt::util; use option::{Some}; #[test] @@ -971,6 +972,7 @@ mod test { #[test] fn test_stress_schedule_task_states() { + if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } let n = stress_factor() * 120; for _ in range(0, n as int) { test_schedule_home_states(); diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs index 792ea5eb33f5a..ad281408966ed 100644 --- a/src/libstd/rt/test.rs +++ b/src/libstd/rt/test.rs @@ -18,7 +18,7 @@ use iterator::{Iterator, range}; use vec::{OwnedVector, MutableVector}; use super::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr}; use rt::sched::Scheduler; -use unstable::run_in_bare_thread; +use unstable::{run_in_bare_thread}; use rt::thread::Thread; use rt::task::Task; use rt::uv::uvio::UvEventLoop; @@ -156,10 +156,14 @@ pub fn run_in_mt_newsched_task(f: ~fn()) { let nthreads = match os::getenv("RUST_RT_TEST_THREADS") { Some(nstr) => FromStr::from_str(nstr).unwrap(), None => { - // 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 + if util::limit_thread_creation_due_to_osx_and_valgrind() { + 1 + } else { + // 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 + } } }; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 40e5c8d4bf1a0..1886790c708d3 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -15,6 +15,7 @@ use libc; use option::{Some, None}; use os; use str::StrSlice; +use unstable::running_on_valgrind; /// Get the number of cores available pub fn num_cpus() -> uint { @@ -27,12 +28,35 @@ pub fn num_cpus() -> uint { } } +/// Valgrind has a fixed-sized array (size around 2000) of segment descriptors wired into it; this +/// is a hard limit and requires rebuilding valgrind if you want to go beyond it. Normally this is +/// not a problem, but in some tests, we produce a lot of threads casually. Making lots of threads +/// alone might not be a problem _either_, except on OSX, the segments produced for new threads +/// _take a while_ to get reclaimed by the OS. Combined with the fact that libuv schedulers fork off +/// a separate thread for polling fsevents on OSX, we get a perfect storm of creating "too many +/// mappings" for valgrind to handle when running certain stress tests in the runtime. +#[cfg(target_os="macos")] +pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { + running_on_valgrind() +} + +#[cfg(not(target_os="macos"))] +pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool { + false +} + /// Get's the number of scheduler threads requested by the environment /// either `RUST_THREADS` or `num_cpus`. pub fn default_sched_threads() -> uint { match os::getenv("RUST_THREADS") { Some(nstr) => FromStr::from_str(nstr).unwrap(), - None => num_cpus() + None => { + if limit_thread_creation_due_to_osx_and_valgrind() { + 1 + } else { + num_cpus() + } + } } } diff --git a/src/libstd/run.rs b/src/libstd/run.rs index ef3d881c5fead..d5f57692aa6d4 100644 --- a/src/libstd/run.rs +++ b/src/libstd/run.rs @@ -923,6 +923,7 @@ mod tests { use path::Path; use run; use str; + use unstable::running_on_valgrind; #[test] #[cfg(windows)] @@ -1331,12 +1332,4 @@ mod tests { assert!(output.contains("RUN_TEST_NEW_ENV=123")); } - - fn running_on_valgrind() -> bool { - unsafe { rust_running_on_valgrind() != 0 } - } - - extern { - fn rust_running_on_valgrind() -> uintptr_t; - } } diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs index f721dd47a66a0..7a6f9bd6d2224 100644 --- a/src/libstd/unstable/mod.rs +++ b/src/libstd/unstable/mod.rs @@ -14,6 +14,7 @@ use comm::{GenericChan, GenericPort}; use comm; use prelude::*; use task; +use libc::uintptr_t; pub mod dynamic_lib; @@ -116,3 +117,16 @@ pub fn change_dir_locked(p: &Path, action: &fn()) -> bool { fn rust_drop_change_dir_lock(); } } + + +/// Dynamically inquire about whether we're running under V. +/// You should usually not use this unless your test definitely +/// can't run correctly un-altered. Valgrind is there to help +/// you notice weirdness in normal, un-doctored code paths! +pub fn running_on_valgrind() -> bool { + unsafe { rust_running_on_valgrind() != 0 } +} + +extern { + fn rust_running_on_valgrind() -> uintptr_t; +}