|
| 1 | +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT |
| 2 | +// file at the top-level directory of this distribution and at |
| 3 | +// http://rust-lang.org/COPYRIGHT. |
| 4 | +// |
| 5 | +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| 6 | +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| 7 | +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your |
| 8 | +// option. This file may not be copied, modified, or distributed |
| 9 | +// except according to those terms. |
| 10 | + |
| 11 | +/// darwin_fd_limit exists to work around an issue where launchctl on Mac OS X |
| 12 | +/// defaults the rlimit maxfiles to 256/unlimited. The default soft limit of 256 |
| 13 | +/// ends up being far too low for our multithreaded scheduler testing, depending |
| 14 | +/// on the number of cores available. |
| 15 | +/// |
| 16 | +/// This fixes issue #7772. |
| 17 | +#[cfg(any(target_os = "macos", target_os = "ios"))] |
| 18 | +#[allow(non_camel_case_types)] |
| 19 | +pub unsafe fn raise_fd_limit() { |
| 20 | + use libc; |
| 21 | + use std::cmp; |
| 22 | + use std::io; |
| 23 | + use std::mem::size_of_val; |
| 24 | + use std::ptr::null_mut; |
| 25 | + |
| 26 | + type rlim_t = libc::uint64_t; |
| 27 | + |
| 28 | + #[repr(C)] |
| 29 | + struct rlimit { |
| 30 | + rlim_cur: rlim_t, |
| 31 | + rlim_max: rlim_t |
| 32 | + } |
| 33 | + extern { |
| 34 | + // name probably doesn't need to be mut, but the C function doesn't |
| 35 | + // specify const |
| 36 | + fn sysctl(name: *mut libc::c_int, namelen: libc::c_uint, |
| 37 | + oldp: *mut libc::c_void, oldlenp: *mut libc::size_t, |
| 38 | + newp: *mut libc::c_void, newlen: libc::size_t) -> libc::c_int; |
| 39 | + fn getrlimit(resource: libc::c_int, rlp: *mut rlimit) -> libc::c_int; |
| 40 | + fn setrlimit(resource: libc::c_int, rlp: *const rlimit) -> libc::c_int; |
| 41 | + } |
| 42 | + static CTL_KERN: libc::c_int = 1; |
| 43 | + static KERN_MAXFILESPERPROC: libc::c_int = 29; |
| 44 | + static RLIMIT_NOFILE: libc::c_int = 8; |
| 45 | + |
| 46 | + // The strategy here is to fetch the current resource limits, read the |
| 47 | + // kern.maxfilesperproc sysctl value, and bump the soft resource limit for |
| 48 | + // maxfiles up to the sysctl value. |
| 49 | + |
| 50 | + // Fetch the kern.maxfilesperproc value |
| 51 | + let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC]; |
| 52 | + let mut maxfiles: libc::c_int = 0; |
| 53 | + let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t; |
| 54 | + if sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, |
| 55 | + null_mut(), 0) != 0 { |
| 56 | + let err = io::Error::last_os_error(); |
| 57 | + panic!("raise_fd_limit: error calling sysctl: {}", err); |
| 58 | + } |
| 59 | + |
| 60 | + // Fetch the current resource limits |
| 61 | + let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0}; |
| 62 | + if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 { |
| 63 | + let err = io::Error::last_os_error(); |
| 64 | + panic!("raise_fd_limit: error calling getrlimit: {}", err); |
| 65 | + } |
| 66 | + |
| 67 | + // Bump the soft limit to the smaller of kern.maxfilesperproc and the hard |
| 68 | + // limit |
| 69 | + rlim.rlim_cur = cmp::min(maxfiles as rlim_t, rlim.rlim_max); |
| 70 | + |
| 71 | + // Set our newly-increased resource limit |
| 72 | + if setrlimit(RLIMIT_NOFILE, &rlim) != 0 { |
| 73 | + let err = io::Error::last_os_error(); |
| 74 | + panic!("raise_fd_limit: error calling setrlimit: {}", err); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +#[cfg(not(any(target_os = "macos", target_os = "ios")))] |
| 79 | +pub unsafe fn raise_fd_limit() {} |
0 commit comments