proxy: Mark ENFILES and EMFILES as survivable.
I don't love this approach, but those errors aren't distinguished by ErrorKind, so we have to use libc or winapi, apparently. At least nothing here is unsafe. Addresses part of #188.
This commit is contained in:
parent
02b20edeb3
commit
0cb7231649
|
@ -98,6 +98,7 @@ dependencies = [
|
||||||
"async-ctrlc",
|
"async-ctrlc",
|
||||||
"config",
|
"config",
|
||||||
"futures",
|
"futures",
|
||||||
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -107,6 +108,7 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-journald",
|
"tracing-journald",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -34,3 +34,9 @@ tracing-subscriber = "0.2.19"
|
||||||
tokio-crate = { package="tokio", version = "1.7.0", optional = true, features = ["signal"] }
|
tokio-crate = { package="tokio", version = "1.7.0", optional = true, features = ["signal"] }
|
||||||
argh = "0.1.6"
|
argh = "0.1.6"
|
||||||
tracing-journald = { version = "0.1.0", optional = true }
|
tracing-journald = { version = "0.1.0", optional = true }
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
libc = { version = "0.2.103", default-features = false }
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
|
winapi = { version = "0.3.8", features = [ "winerror" ] }
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//! connections and then runs
|
//! connections and then runs
|
||||||
|
|
||||||
use futures::future::FutureExt;
|
use futures::future::FutureExt;
|
||||||
use futures::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
|
use futures::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, Error as IoError};
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use futures::task::SpawnExt;
|
use futures::task::SpawnExt;
|
||||||
|
@ -334,6 +334,21 @@ where
|
||||||
loop_result.or(flush_result)
|
loop_result.or(flush_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if a given IoError, when received from accept, is a fatal
|
||||||
|
/// error.
|
||||||
|
fn accept_err_is_fatal(err: &IoError) -> bool {
|
||||||
|
#![allow(clippy::match_like_matches_macro)]
|
||||||
|
// Currently, EMFILE and ENFILE aren't distinguished by ErrorKind;
|
||||||
|
// we need to use OS-specific errors. :P
|
||||||
|
match err.raw_os_error() {
|
||||||
|
#[cfg(unix)]
|
||||||
|
Some(libc::EMFILE) | Some(libc::ENFILE) => false,
|
||||||
|
#[cfg(windows)]
|
||||||
|
Some(winapi::shared::winerror::WSAEMFILE) => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Launch a SOCKS proxy to listen on a given localhost port, and run
|
/// Launch a SOCKS proxy to listen on a given localhost port, and run
|
||||||
/// indefinitely.
|
/// indefinitely.
|
||||||
///
|
///
|
||||||
|
@ -386,7 +401,17 @@ pub(crate) async fn run_socks_proxy<R: Runtime>(
|
||||||
// Loop over all incoming connections. For each one, call
|
// Loop over all incoming connections. For each one, call
|
||||||
// handle_socks_conn() in a new task.
|
// handle_socks_conn() in a new task.
|
||||||
while let Some((stream, sock_id)) = incoming.next().await {
|
while let Some((stream, sock_id)) = incoming.next().await {
|
||||||
let (stream, addr) = stream.context("Failed to receive incoming stream on SOCKS port")?;
|
let (stream, addr) = match stream {
|
||||||
|
Ok((s, a)) => (s, a),
|
||||||
|
Err(err) => {
|
||||||
|
if accept_err_is_fatal(&err) {
|
||||||
|
return Err(err).context("Failed to receive incoming stream on SOCKS port");
|
||||||
|
} else {
|
||||||
|
warn!("Incoming stream failed: {}", err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
let client_ref = Arc::clone(&tor_client);
|
let client_ref = Arc::clone(&tor_client);
|
||||||
let runtime_copy = runtime.clone();
|
let runtime_copy = runtime.clone();
|
||||||
let isolation_map_ref = Arc::clone(&isolation_map);
|
let isolation_map_ref = Arc::clone(&isolation_map);
|
||||||
|
|
Loading…
Reference in New Issue