diff options
author | cyqsimon <28627918+cyqsimon@users.noreply.github.com> | 2023-10-20 19:25:27 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-20 19:25:27 +0800 |
commit | 89e1140bea689c5790029bd02aea74b6b5ac0bea (patch) | |
tree | e7711ada0482631c1ac2ad5bd82f2be5d894872d | |
parent | 0c4987aa86dc5210c11024b74f3f8947ba1358ac (diff) |
Make logging race-free using a global lock & macro (#309)
* Make logging race-free using a global lock & macro
* Fix clippy complaint
* Fix import for MacOS
* Make `mt_log` expand to an expression
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/display/ui_state.rs | 14 | ||||
-rw-r--r-- | src/main.rs | 16 | ||||
-rw-r--r-- | src/os/lsof_utils.rs | 21 |
5 files changed, 42 insertions, 11 deletions
@@ -158,6 +158,7 @@ dependencies = [ "itertools", "log", "netstat2", + "once_cell", "packet-builder", "pnet", "pnet_base", @@ -41,6 +41,7 @@ simplelog = "0.12.1" clap-verbosity-flag = "2.0.1" derivative = "2.2.0" itertools = "0.11.0" +once_cell = "1.18.0" [target.'cfg(target_os="windows")'.dependencies] netstat2 = "0.9.1" diff --git a/src/display/ui_state.rs b/src/display/ui_state.rs index 55d0f09..e88cde1 100644 --- a/src/display/ui_state.rs +++ b/src/display/ui_state.rs @@ -7,9 +7,10 @@ use std::{ net::{IpAddr, Ipv4Addr, Ipv6Addr}, }; -use log::warn; - -use crate::network::{Connection, LocalSocket, Utilization}; +use crate::{ + mt_log, + network::{Connection, LocalSocket, Utilization}, +}; static RECALL_LENGTH: usize = 5; static MAX_BANDWIDTH_ITEMS: usize = 1000; @@ -141,12 +142,13 @@ impl UIState { }, ) { Some((lookalike, name)) => { - warn!( + mt_log!( + warn, r#""{name}" owns a similar looking connection, but its local ip doesn't match."# ); - warn!("Looking for: {local_socket}; found: {lookalike}"); + mt_log!(warn, "Looking for: {local_socket}; found: {lookalike}"); } - None => warn!("Cannot determine which process owns {local_socket}."), + None => mt_log!(warn, "Cannot determine which process owns {local_socket}."), }; } } diff --git a/src/main.rs b/src/main.rs index 72d4528..87c5cf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ use network::{ dns::{self, IpTable}, LocalSocket, Sniffer, Utilization, }; +use once_cell::sync::Lazy; use pnet::datalink::{DataLinkReceiver, NetworkInterface}; use ratatui::backend::{Backend, CrosstermBackend}; use simplelog::WriteLogger; @@ -36,6 +37,21 @@ use crate::cli::Opt; const DISPLAY_DELTA: Duration = Duration::from_millis(1000); +/// Lock guard to prevent races during logging. +static LOG_LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(())); + +/// Thread-safe log macro with a global Mutex guard. +#[macro_export] +macro_rules! mt_log { + ($log_macro: ident, $($fmt_args:expr),*) => {{ + let guard = $crate::LOG_LOCK + .lock() + .unwrap_or_else(|poisoned| poisoned.into_inner()); + log::$log_macro!($($fmt_args,)*); + drop(guard); + }}; +} + fn main() -> anyhow::Result<()> { let opts = Opt::parse(); diff --git a/src/os/lsof_utils.rs b/src/os/lsof_utils.rs index 5e55dad..166b9c9 100644 --- a/src/os/lsof_utils.rs +++ b/src/os/lsof_utils.rs @@ -1,9 +1,11 @@ use std::{ffi::OsStr, net::IpAddr, process::Command, sync::OnceLock}; -use log::warn; use regex::Regex; -use crate::network::{LocalSocket, Protocol}; +use crate::{ + mt_log, + network::{LocalSocket, Protocol}, +}; #[allow(dead_code)] #[derive(Debug, Clone)] @@ -120,15 +122,24 @@ impl RawConnection { let process = &self.process_name; let Some(ip) = self.get_local_ip() else { - warn!(r#"Failed to get the local IP of a connection belonging to "{process}"."#); + mt_log!( + warn, + r#"Failed to get the local IP of a connection belonging to "{process}"."# + ); return None; }; let Some(port) = self.get_local_port() else { - warn!(r#"Failed to get the local port of a connection belonging to "{process}"."#); + mt_log!( + warn, + r#"Failed to get the local port of a connection belonging to "{process}"."# + ); return None; }; let Some(protocol) = self.get_protocol() else { - warn!(r#"Failed to get the protocol of a connection belonging to "{process}"."#); + mt_log!( + warn, + r#"Failed to get the protocol of a connection belonging to "{process}"."# + ); return None; }; |