Skip to content

Commit 2001cc0

Browse files
committed
Bump fd limit on macos when running rt tests
OS X defaults the ulimit for open files to 256 for programs launched from the Terminal (GUI apps get a higher default). Unfortunately this is too low for the rt tests, which deliberately overcommit and create a lot of threads (which means a lot of schedulers, and each scheduler needs at least 2 fds). By calling sysctl() and setrlimit() we can bump the fd limit up to the maximum allowed (on stock OS X it's 10240). Fixes #7772.
1 parent 70d2be0 commit 2001cc0

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

src/libstd/rt/test.rs

+78
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,81 @@ pub fn run_in_newsched_task_core(f: ~fn()) {
6363
sched.bootstrap(task);
6464
}
6565

66+
#[cfg(target_os="macos")]
67+
#[allow(non_camel_case_types)]
68+
mod darwin_fd_limit {
69+
/*!
70+
* darwin_fd_limit exists to work around an issue where launchctl on Mac OS X defaults the
71+
* rlimit maxfiles to 256/unlimited. The default soft limit of 256 ends up being far too low
72+
* for our multithreaded scheduler testing, depending on the number of cores available.
73+
*
74+
* This fixes issue #7772.
75+
*/
76+
77+
use libc;
78+
type rlim_t = libc::uint64_t;
79+
struct rlimit {
80+
rlim_cur: rlim_t,
81+
rlim_max: rlim_t
82+
}
83+
#[nolink]
84+
extern {
85+
// name probably doesn't need to be mut, but the C function doesn't specify const
86+
fn sysctl(name: *mut libc::c_int, namelen: libc::c_uint,
87+
oldp: *mut libc::c_void, oldlenp: *mut libc::size_t,
88+
newp: *mut libc::c_void, newlen: libc::size_t) -> libc::c_int;
89+
fn getrlimit(resource: libc::c_int, rlp: *mut rlimit) -> libc::c_int;
90+
fn setrlimit(resource: libc::c_int, rlp: *rlimit) -> libc::c_int;
91+
}
92+
static CTL_KERN: libc::c_int = 1;
93+
static KERN_MAXFILESPERPROC: libc::c_int = 29;
94+
static RLIMIT_NOFILE: libc::c_int = 8;
95+
96+
pub unsafe fn raise_fd_limit() {
97+
// The strategy here is to fetch the current resource limits, read the kern.maxfilesperproc
98+
// sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
99+
use ptr::{to_unsafe_ptr, to_mut_unsafe_ptr, mut_null};
100+
use sys::size_of_val;
101+
use os::last_os_error;
102+
103+
// Fetch the kern.maxfilesperproc value
104+
let mut mib: [libc::c_int, ..2] = [CTL_KERN, KERN_MAXFILESPERPROC];
105+
let mut maxfiles: libc::c_int = 0;
106+
let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
107+
if sysctl(to_mut_unsafe_ptr(&mut mib[0]), 2,
108+
to_mut_unsafe_ptr(&mut maxfiles) as *mut libc::c_void,
109+
to_mut_unsafe_ptr(&mut size),
110+
mut_null(), 0) != 0 {
111+
let err = last_os_error();
112+
error!("raise_fd_limit: error calling sysctl: %s", err);
113+
return;
114+
}
115+
116+
// Fetch the current resource limits
117+
let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
118+
if getrlimit(RLIMIT_NOFILE, to_mut_unsafe_ptr(&mut rlim)) != 0 {
119+
let err = last_os_error();
120+
error!("raise_fd_limit: error calling getrlimit: %s", err);
121+
return;
122+
}
123+
124+
// Bump the soft limit to the smaller of kern.maxfilesperproc and the hard limit
125+
rlim.rlim_cur = ::cmp::min(maxfiles as rlim_t, rlim.rlim_max);
126+
127+
// Set our newly-increased resource limit
128+
if setrlimit(RLIMIT_NOFILE, to_unsafe_ptr(&rlim)) != 0 {
129+
let err = last_os_error();
130+
error!("raise_fd_limit: error calling setrlimit: %s", err);
131+
return;
132+
}
133+
}
134+
}
135+
136+
#[cfg(not(target_os="macos"))]
137+
mod darwin_fd_limit {
138+
pub unsafe fn raise_fd_limit() {}
139+
}
140+
66141
/// Create more than one scheduler and run a function in a task
67142
/// in one of the schedulers. The schedulers will stay alive
68143
/// until the function `f` returns.
@@ -72,6 +147,9 @@ pub fn run_in_mt_newsched_task(f: ~fn()) {
72147
use rt::sched::Shutdown;
73148
use rt::util;
74149

150+
// Bump the fd limit on OS X. See darwin_fd_limit for an explanation.
151+
unsafe { darwin_fd_limit::raise_fd_limit() }
152+
75153
let f = Cell::new(f);
76154

77155
do run_in_bare_thread {

0 commit comments

Comments
 (0)