Ctrlc issues (#75)

This commit is contained in:
ssrlive 2023-11-06 20:03:40 +08:00 committed by GitHub
parent 9396db4a52
commit 0e654eb4bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 34 deletions

View file

@ -10,7 +10,7 @@ crate-type = ["cdylib", "lib"]
[dependencies] [dependencies]
base64 = { version = "0.21" } base64 = { version = "0.21" }
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
ctrlc = "3.4" ctrlc2 = { version = "3.5", features = ["termination"] }
digest_auth = "0.3" digest_auth = "0.3"
dotenvy = "0.15" dotenvy = "0.15"
env_logger = "0.10" env_logger = "0.10"

View file

@ -3,8 +3,8 @@ pub enum Error {
#[error("std::ffi::NulError {0:?}")] #[error("std::ffi::NulError {0:?}")]
Nul(#[from] std::ffi::NulError), Nul(#[from] std::ffi::NulError),
#[error("ctrlc::Error {0:?}")] #[error("ctrlc2::Error {0:?}")]
InterruptHandler(#[from] ctrlc::Error), InterruptHandler(#[from] ctrlc2::Error),
#[error(transparent)] #[error(transparent)]
Io(#[from] std::io::Error), Io(#[from] std::io::Error),

View file

@ -1176,53 +1176,50 @@ impl<'a> TunToProxy<'a> {
} }
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
fn prepare_exiting_signal_trigger(&mut self) -> Result<()> { fn prepare_exiting_signal_trigger(&mut self) -> Result<std::thread::JoinHandle<()>> {
let mut exit_trigger = self.exit_trigger.take().ok_or("Already running")?; let mut exit_trigger = self.exit_trigger.take().ok_or("Already running")?;
ctrlc::set_handler(move || { let mut count = 0;
let mut count = 0; let handle = ctrlc2::set_handler(move || -> bool {
loop { match exit_trigger.write(b"EXIT") {
match exit_trigger.write(b"EXIT") { Ok(_) => {
Ok(_) => { log::trace!("Exit signal triggered successfully");
log::trace!("Exit signal triggered successfully"); true
break; }
} Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => {
Err(err) if err.kind() == std::io::ErrorKind::WouldBlock => { if count > 5 {
if count > 5 { log::error!("Send exit signal failed 5 times, exit anyway");
log::error!("Send exit signal failed 5 times, exit anyway"); return true; // std::process::exit(1);
std::process::exit(1);
}
log::trace!("Send exit signal failed, retry in 1 second");
std::thread::sleep(std::time::Duration::from_secs(1));
count += 1;
}
Err(err) => {
log::error!("Failed to send exit signal: \"{}\"", err);
break;
} }
count += 1;
false
}
Err(err) => {
log::error!("Failed to send exit signal: \"{}\"", err);
true
} }
} }
})?; })?;
Ok(()) Ok(handle)
} }
pub fn run(&mut self) -> Result<(), Error> { pub fn run(&mut self) -> Result<(), Error> {
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))] #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
self.prepare_exiting_signal_trigger()?; let handle = self.prepare_exiting_signal_trigger()?;
let mut events = Events::with_capacity(1024); let mut events = Events::with_capacity(1024);
loop { let ret = 'exit_point: loop {
if let Err(err) = self.poll.poll(&mut events, None) { if let Err(err) = self.poll.poll(&mut events, None) {
if err.kind() == std::io::ErrorKind::Interrupted { if err.kind() == std::io::ErrorKind::Interrupted {
log::debug!("Poll interrupted: \"{err}\", ignored, continue polling"); log::debug!("Poll interrupted: \"{err}\", ignored, continue polling");
continue; continue;
} }
return Err(err.into()); break 'exit_point Err(Error::from(err));
} }
for event in events.iter() { for event in events.iter() {
match event.token() { match event.token() {
EXIT_TOKEN => { EXIT_TOKEN => {
if self.exiting_event_handler()? { if self.exiting_event_handler()? {
return Ok(()); break 'exit_point Ok(());
} }
} }
EXIT_TRIGGER_TOKEN => { EXIT_TRIGGER_TOKEN => {
@ -1236,7 +1233,11 @@ impl<'a> TunToProxy<'a> {
self.send_to_smoltcp()?; self.send_to_smoltcp()?;
self.clearup_expired_connection()?; self.clearup_expired_connection()?;
self.clearup_expired_dns_over_tcp()?; self.clearup_expired_dns_over_tcp()?;
} };
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
handle.join().unwrap();
log::trace!("{:?}", ret);
ret
} }
fn exiting_event_handler(&mut self) -> Result<bool> { fn exiting_event_handler(&mut self) -> Result<bool> {

View file

@ -3,15 +3,12 @@
mod tests { mod tests {
extern crate reqwest; extern crate reqwest;
use std::env;
use std::net::IpAddr;
use std::str::FromStr;
use fork::Fork; use fork::Fork;
use nix::sys::signal; use nix::sys::signal;
use nix::unistd::Pid; use nix::unistd::Pid;
use serial_test::serial; use serial_test::serial;
use smoltcp::wire::IpCidr; use smoltcp::wire::IpCidr;
use std::env;
use tun2proxy::setup::{get_default_cidrs, Setup}; use tun2proxy::setup::{get_default_cidrs, Setup};
use tun2proxy::util::str_to_cidr; use tun2proxy::util::str_to_cidr;