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",
|
||||
"config",
|
||||
"futures",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"tokio",
|
||||
|
@ -107,6 +108,7 @@ dependencies = [
|
|||
"tracing",
|
||||
"tracing-journald",
|
||||
"tracing-subscriber",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -34,3 +34,9 @@ tracing-subscriber = "0.2.19"
|
|||
tokio-crate = { package="tokio", version = "1.7.0", optional = true, features = ["signal"] }
|
||||
argh = "0.1.6"
|
||||
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
|
||||
|
||||
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::stream::StreamExt;
|
||||
use futures::task::SpawnExt;
|
||||
|
@ -334,6 +334,21 @@ where
|
|||
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
|
||||
/// indefinitely.
|
||||
///
|
||||
|
@ -386,7 +401,17 @@ pub(crate) async fn run_socks_proxy<R: Runtime>(
|
|||
// Loop over all incoming connections. For each one, call
|
||||
// handle_socks_conn() in a new task.
|
||||
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 runtime_copy = runtime.clone();
|
||||
let isolation_map_ref = Arc::clone(&isolation_map);
|
||||
|
|
Loading…
Reference in New Issue