diff --git a/Cargo.lock b/Cargo.lock index c8e60dce6..680b9606e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,12 +703,14 @@ dependencies = [ name = "ethcore-network" version = "1.12.0" dependencies = [ + "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0", "ethcore-io 1.12.0", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethkey 0.3.0", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.1", "snappy 0.1.0 (git+https://github.com/paritytech/rust-snappy)", ] diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index f7131da03..4ae699098 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -14,4 +14,9 @@ ethereum-types = "0.3" ethkey = { path = "../../ethkey" } ipnetwork = "0.12.6" rlp = { path = "../rlp" } +libc = "0.2" snappy = { git = "https://github.com/paritytech/rust-snappy" } + + +[dev-dependencies] +assert_matches = "1.2" diff --git a/util/network/src/error.rs b/util/network/src/error.rs index 610448669..50bd01e9b 100644 --- a/util/network/src/error.rs +++ b/util/network/src/error.rs @@ -15,6 +15,7 @@ // along with Parity. If not, see . use std::{io, net, fmt}; +use libc::{ENFILE, EMFILE}; use io::IoError; use {rlp, ethkey, crypto, snappy}; @@ -83,7 +84,6 @@ impl fmt::Display for DisconnectReason { error_chain! { foreign_links { SocketIo(IoError) #[doc = "Socket IO error."]; - Io(io::Error) #[doc = "Error concerning the Rust standard library's IO subsystem."]; Decompression(snappy::InvalidInput) #[doc = "Decompression error."]; } @@ -141,6 +141,34 @@ error_chain! { description("Packet is too large"), display("Packet is too large"), } + + #[doc = "Reached system resource limits for this process"] + ProcessTooManyFiles { + description("Too many open files in process."), + display("Too many open files in this process. Check your resource limits and restart parity"), + } + + #[doc = "Reached system wide resource limits"] + SystemTooManyFiles { + description("Too many open files on system."), + display("Too many open files on system. Consider closing some processes/release some file handlers or increas the system-wide resource limits and restart parity."), + } + + #[doc = "An unknown IO error occurred."] + Io(err: io::Error) { + description("IO Error"), + display("Unexpected IO error: {}", err), + } + } +} + +impl From for Error { + fn from(err: io::Error) -> Self { + match err.raw_os_error() { + Some(ENFILE) => ErrorKind::ProcessTooManyFiles.into(), + Some(EMFILE) => ErrorKind::SystemTooManyFiles.into(), + _ => Error::from_kind(ErrorKind::Io(err)) + } } } @@ -191,3 +219,26 @@ fn test_errors() { _ => panic!("Unexpected error"), } } + +#[test] +fn test_io_errors() { + use libc::{EMFILE, ENFILE}; + + assert_matches!( + >::from( + io::Error::from_raw_os_error(ENFILE) + ).kind(), + ErrorKind::ProcessTooManyFiles); + + assert_matches!( + >::from( + io::Error::from_raw_os_error(EMFILE) + ).kind(), + ErrorKind::SystemTooManyFiles); + + assert_matches!( + >::from( + io::Error::from_raw_os_error(0) + ).kind(), + ErrorKind::Io(_)); +} diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index 207a05075..87d3ed9b0 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -23,6 +23,10 @@ extern crate ethkey; extern crate rlp; extern crate ipnetwork; extern crate snappy; +extern crate libc; + +#[cfg(test)] #[macro_use] +extern crate assert_matches; #[macro_use] extern crate error_chain;