diff --git a/Cargo.toml b/Cargo.toml index 6766a5b2c..1eac83ac3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ ethcore-util = { path = "util" } ethcore = { path = "ethcore" } ethsync = { path = "sync" } ethcore-rpc = { path = "rpc", optional = true } +fdlimit = { path = "util/fdlimit" } [features] default = ["rpc"] diff --git a/parity/main.rs b/parity/main.rs index 7d0a08855..2aa0f7070 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -28,6 +28,7 @@ extern crate ethsync; extern crate log as rlog; extern crate env_logger; extern crate ctrlc; +extern crate fdlimit; #[cfg(feature = "rpc")] extern crate ethcore_rpc as rpc; @@ -95,6 +96,7 @@ fn main() { let args: Args = Args::docopt().decode().unwrap_or_else(|e| e.exit()); setup_log(&args.flag_logging); + unsafe { ::fdlimit::raise_fd_limit(); } let spec = ethereum::new_frontier(); let init_nodes = match args.arg_enode.len() { diff --git a/util/fdlimit/Cargo.toml b/util/fdlimit/Cargo.toml new file mode 100644 index 000000000..42aa582fe --- /dev/null +++ b/util/fdlimit/Cargo.toml @@ -0,0 +1,10 @@ +[package] +description = "Utility function to raise file descriptor limit on OS X" +homepage = "http://ethcore.io" +license = "GPL-3.0" +name = "fdlimit" +version = "0.1.0" +authors = ["Ethcore "] + +[dependencies] +libc = "0.2" diff --git a/util/fdlimit/src/lib.rs b/util/fdlimit/src/lib.rs new file mode 100644 index 000000000..e659bb8c9 --- /dev/null +++ b/util/fdlimit/src/lib.rs @@ -0,0 +1,18 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. +// +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see .extern crate libc; +extern crate libc; +pub mod raise_fd_limit; +pub use raise_fd_limit::raise_fd_limit; diff --git a/util/fdlimit/src/raise_fd_limit.rs b/util/fdlimit/src/raise_fd_limit.rs new file mode 100644 index 000000000..f57ac2785 --- /dev/null +++ b/util/fdlimit/src/raise_fd_limit.rs @@ -0,0 +1,61 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// 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. +/// +#[cfg(any(target_os = "macos", target_os = "ios"))] +#[allow(non_camel_case_types)] +pub unsafe fn raise_fd_limit() { + use libc; + use std::cmp; + use std::io; + use std::mem::size_of_val; + use std::ptr::null_mut; + + static CTL_KERN: libc::c_int = 1; + static KERN_MAXFILESPERPROC: libc::c_int = 29; + + // 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. + + // 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 libc::sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size, + null_mut(), 0) != 0 { + let err = io::Error::last_os_error(); + panic!("raise_fd_limit: error calling sysctl: {}", err); + } + + // Fetch the current resource limits + let mut rlim = libc::rlimit{rlim_cur: 0, rlim_max: 0}; + if libc::getrlimit(libc::RLIMIT_NOFILE, &mut rlim) != 0 { + let err = io::Error::last_os_error(); + panic!("raise_fd_limit: error calling getrlimit: {}", err); + } + + // Bump the soft limit to the smaller of kern.maxfilesperproc and the hard + // limit + rlim.rlim_cur = cmp::min(maxfiles as libc::rlim_t, rlim.rlim_max); + + // Set our newly-increased resource limit + if libc::setrlimit(libc::RLIMIT_NOFILE, &rlim) != 0 { + let err = io::Error::last_os_error(); + panic!("raise_fd_limit: error calling setrlimit: {}", err); + } +} + +#[cfg(not(any(target_os = "macos", target_os = "ios")))] +pub unsafe fn raise_fd_limit() {}