summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGarrett Thornburg <film42@gmail.com>2021-08-09 23:32:08 -0600
committerAndrew Gallant <jamslam@gmail.com>2023-07-08 18:52:42 -0400
commit4782ebd5e0773465ba2c32a328250253c2b55779 (patch)
tree758ef63975bb1195496ff877d8721e9309100908
parent4993d29a16b26b016b498765cc5636e73b479367 (diff)
core: lock stdout before printing an error message to stderr
Adds a new eprintln_locked macro which locks STDOUT before logging to STDERR. This patch also replaces instances of eprintln with eprintln_locked to avoid interleaving lines. Fixes #1941, Closes #1968
-rw-r--r--crates/core/logger.rs8
-rw-r--r--crates/core/main.rs2
-rw-r--r--crates/core/messages.rs20
3 files changed, 23 insertions, 7 deletions
diff --git a/crates/core/logger.rs b/crates/core/logger.rs
index 0fe063f1..0c5414c7 100644
--- a/crates/core/logger.rs
+++ b/crates/core/logger.rs
@@ -33,7 +33,7 @@ impl Log for Logger {
fn log(&self, record: &log::Record<'_>) {
match (record.file(), record.line()) {
(Some(file), Some(line)) => {
- eprintln!(
+ eprintln_locked!(
"{}|{}|{}:{}: {}",
record.level(),
record.target(),
@@ -43,7 +43,7 @@ impl Log for Logger {
);
}
(Some(file), None) => {
- eprintln!(
+ eprintln_locked!(
"{}|{}|{}: {}",
record.level(),
record.target(),
@@ -52,7 +52,7 @@ impl Log for Logger {
);
}
_ => {
- eprintln!(
+ eprintln_locked!(
"{}|{}: {}",
record.level(),
record.target(),
@@ -63,6 +63,6 @@ impl Log for Logger {
}
fn flush(&self) {
- // We use eprintln! which is flushed on every call.
+ // We use eprintln_locked! which is flushed on every call.
}
}
diff --git a/crates/core/main.rs b/crates/core/main.rs
index 2584ea9f..eff4da1f 100644
--- a/crates/core/main.rs
+++ b/crates/core/main.rs
@@ -47,7 +47,7 @@ type Result<T> = ::std::result::Result<T, Box<dyn error::Error>>;
fn main() {
if let Err(err) = Args::parse().and_then(try_main) {
- eprintln!("{}", err);
+ eprintln_locked!("{}", err);
process::exit(2);
}
}
diff --git a/crates/core/messages.rs b/crates/core/messages.rs
index dc013e1c..be9e10dc 100644
--- a/crates/core/messages.rs
+++ b/crates/core/messages.rs
@@ -4,12 +4,28 @@ static MESSAGES: AtomicBool = AtomicBool::new(false);
static IGNORE_MESSAGES: AtomicBool = AtomicBool::new(false);
static ERRORED: AtomicBool = AtomicBool::new(false);
+/// Like eprintln, but locks STDOUT to prevent interleaving lines.
+#[macro_export]
+macro_rules! eprintln_locked {
+ ($($tt:tt)*) => {{
+ {
+ // This is a bit of an abstraction violation because we explicitly
+ // lock STDOUT before printing to STDERR. This avoids interleaving
+ // lines within ripgrep because `search_parallel` uses `termcolor`,
+ // which accesses the same STDOUT lock when writing lines.
+ let stdout = std::io::stdout();
+ let _handle = stdout.lock();
+ eprintln!($($tt)*);
+ }
+ }}
+}
+
/// Emit a non-fatal error message, unless messages were disabled.
#[macro_export]
macro_rules! message {
($($tt:tt)*) => {
if crate::messages::messages() {
- eprintln!($($tt)*);
+ eprintln_locked!($($tt)*);
}
}
}
@@ -30,7 +46,7 @@ macro_rules! err_message {
macro_rules! ignore_message {
($($tt:tt)*) => {
if crate::messages::messages() && crate::messages::ignore_messages() {
- eprintln!($($tt)*);
+ eprintln_locked!($($tt)*);
}
}
}