Skip to content

Commit 89e1140

Browse files
authored
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
1 parent 0c4987a commit 89e1140

File tree

5 files changed

+42
-11
lines changed

5 files changed

+42
-11
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ simplelog = "0.12.1"
4141
clap-verbosity-flag = "2.0.1"
4242
derivative = "2.2.0"
4343
itertools = "0.11.0"
44+
once_cell = "1.18.0"
4445

4546
[target.'cfg(target_os="windows")'.dependencies]
4647
netstat2 = "0.9.1"

src/display/ui_state.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use std::{
77
net::{IpAddr, Ipv4Addr, Ipv6Addr},
88
};
99

10-
use log::warn;
11-
12-
use crate::network::{Connection, LocalSocket, Utilization};
10+
use crate::{
11+
mt_log,
12+
network::{Connection, LocalSocket, Utilization},
13+
};
1314

1415
static RECALL_LENGTH: usize = 5;
1516
static MAX_BANDWIDTH_ITEMS: usize = 1000;
@@ -141,12 +142,13 @@ impl UIState {
141142
},
142143
) {
143144
Some((lookalike, name)) => {
144-
warn!(
145+
mt_log!(
146+
warn,
145147
r#""{name}" owns a similar looking connection, but its local ip doesn't match."#
146148
);
147-
warn!("Looking for: {local_socket}; found: {lookalike}");
149+
mt_log!(warn, "Looking for: {local_socket}; found: {lookalike}");
148150
}
149-
None => warn!("Cannot determine which process owns {local_socket}."),
151+
None => mt_log!(warn, "Cannot determine which process owns {local_socket}."),
150152
};
151153
}
152154
}

src/main.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use network::{
2828
dns::{self, IpTable},
2929
LocalSocket, Sniffer, Utilization,
3030
};
31+
use once_cell::sync::Lazy;
3132
use pnet::datalink::{DataLinkReceiver, NetworkInterface};
3233
use ratatui::backend::{Backend, CrosstermBackend};
3334
use simplelog::WriteLogger;
@@ -36,6 +37,21 @@ use crate::cli::Opt;
3637

3738
const DISPLAY_DELTA: Duration = Duration::from_millis(1000);
3839

40+
/// Lock guard to prevent races during logging.
41+
static LOG_LOCK: Lazy<Mutex<()>> = Lazy::new(|| Mutex::new(()));
42+
43+
/// Thread-safe log macro with a global Mutex guard.
44+
#[macro_export]
45+
macro_rules! mt_log {
46+
($log_macro: ident, $($fmt_args:expr),*) => {{
47+
let guard = $crate::LOG_LOCK
48+
.lock()
49+
.unwrap_or_else(|poisoned| poisoned.into_inner());
50+
log::$log_macro!($($fmt_args,)*);
51+
drop(guard);
52+
}};
53+
}
54+
3955
fn main() -> anyhow::Result<()> {
4056
let opts = Opt::parse();
4157

src/os/lsof_utils.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::{ffi::OsStr, net::IpAddr, process::Command, sync::OnceLock};
22

3-
use log::warn;
43
use regex::Regex;
54

6-
use crate::network::{LocalSocket, Protocol};
5+
use crate::{
6+
mt_log,
7+
network::{LocalSocket, Protocol},
8+
};
79

810
#[allow(dead_code)]
911
#[derive(Debug, Clone)]
@@ -120,15 +122,24 @@ impl RawConnection {
120122
let process = &self.process_name;
121123

122124
let Some(ip) = self.get_local_ip() else {
123-
warn!(r#"Failed to get the local IP of a connection belonging to "{process}"."#);
125+
mt_log!(
126+
warn,
127+
r#"Failed to get the local IP of a connection belonging to "{process}"."#
128+
);
124129
return None;
125130
};
126131
let Some(port) = self.get_local_port() else {
127-
warn!(r#"Failed to get the local port of a connection belonging to "{process}"."#);
132+
mt_log!(
133+
warn,
134+
r#"Failed to get the local port of a connection belonging to "{process}"."#
135+
);
128136
return None;
129137
};
130138
let Some(protocol) = self.get_protocol() else {
131-
warn!(r#"Failed to get the protocol of a connection belonging to "{process}"."#);
139+
mt_log!(
140+
warn,
141+
r#"Failed to get the protocol of a connection belonging to "{process}"."#
142+
);
132143
return None;
133144
};
134145

0 commit comments

Comments
 (0)