From 45128ef135a3305ccc59c43578964820ef2f014c Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 3 Oct 2025 11:38:58 +0800 Subject: [PATCH 1/7] refactor: call flush_atexit at exit Signed-off-by: tison --- spdlog/src/lib.rs | 5 +--- spdlog/src/logger.rs | 8 +++++ spdlog/src/sink/async_sink/async_pool_sink.rs | 30 +++++++++---------- spdlog/src/sink/mod.rs | 7 +++++ 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/spdlog/src/lib.rs b/spdlog/src/lib.rs index 624762c5..141ae3e5 100644 --- a/spdlog/src/lib.rs +++ b/spdlog/src/lib.rs @@ -736,8 +736,6 @@ pub fn log_crate_proxy() -> &'static LogCrateProxy { &PROXY } -static IS_TEARING_DOWN: AtomicBool = AtomicBool::new(false); - fn flush_default_logger_at_exit() { // Rust never calls `drop` for static variables. // @@ -745,9 +743,8 @@ fn flush_default_logger_at_exit() { // once at the program exit, thus we don't lose the last logs. extern "C" fn handler() { - IS_TEARING_DOWN.store(true, Ordering::SeqCst); if let Some(default_logger) = DEFAULT_LOGGER.get() { - default_logger.load().flush() + default_logger.load().flush_sinks_atexit() } } diff --git a/spdlog/src/logger.rs b/spdlog/src/logger.rs index 1b769aab..3ee97138 100644 --- a/spdlog/src/logger.rs +++ b/spdlog/src/logger.rs @@ -470,6 +470,14 @@ impl Logger { }) } + pub(crate) fn flush_sinks_atexit(&self) { + self.sinks.iter().for_each(|sink| { + if let Err(err) = sink.flush_atexit() { + self.handle_error(err); + } + }); + } + // This will lose the periodic flush property, if any. #[must_use] fn clone_lossy(&self) -> Self { diff --git a/spdlog/src/sink/async_sink/async_pool_sink.rs b/spdlog/src/sink/async_sink/async_pool_sink.rs index 85833337..1d7d6ab2 100644 --- a/spdlog/src/sink/async_sink/async_pool_sink.rs +++ b/spdlog/src/sink/async_sink/async_pool_sink.rs @@ -129,21 +129,21 @@ impl Sink for AsyncPoolSink { } fn flush(&self) -> Result<()> { - if crate::IS_TEARING_DOWN.load(Ordering::SeqCst) { - // https://github.com/SpriteOvO/spdlog-rs/issues/64 - // - // If the program is tearing down, this will be the final flush. `crossbeam` - // uses thread-local internally, which is not supported in `atexit` callback. - // This can be bypassed by flushing sinks directly on the current thread, but - // before we do that we have to destroy the thread pool to ensure that any - // pending log tasks are completed. - self.thread_pool.destroy(); - self.backend.flush() - } else { - self.assign_task(Task::Flush { - backend: self.clone_backend(), - }) - } + self.assign_task(Task::Flush { + backend: self.clone_backend(), + }) + } + + fn flush_atexit(&self) -> Result<()> { + // https://github.com/SpriteOvO/spdlog-rs/issues/64 + // + // If the program is tearing down, this will be the final flush. `crossbeam` + // uses thread-local internally, which is not supported in `atexit` callback. + // This can be bypassed by flushing sinks directly on the current thread, but + // before we do that we have to destroy the thread pool to ensure that any + // pending log tasks are completed. + self.thread_pool.destroy(); + self.backend.flush() } } diff --git a/spdlog/src/sink/mod.rs b/spdlog/src/sink/mod.rs index dbdc250f..fd893a1e 100644 --- a/spdlog/src/sink/mod.rs +++ b/spdlog/src/sink/mod.rs @@ -231,6 +231,13 @@ pub trait Sink: SinkPropAccess + Sync + Send { /// Flushes any buffered records. fn flush(&self) -> Result<()>; + + /// Flushes any buffered records at program exit. + /// + /// Default to call `flush()`. + fn flush_atexit(&self) -> Result<()> { + self.flush() + } } /// Container type for [`Sink`]s. From ce175c2ebcc08cddba1ba328d3db15664796cbce Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 3 Oct 2025 23:41:45 +0800 Subject: [PATCH 2/7] Update spdlog/src/sink/async_sink/async_pool_sink.rs --- spdlog/src/sink/async_sink/async_pool_sink.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spdlog/src/sink/async_sink/async_pool_sink.rs b/spdlog/src/sink/async_sink/async_pool_sink.rs index 1d7d6ab2..ad9d8505 100644 --- a/spdlog/src/sink/async_sink/async_pool_sink.rs +++ b/spdlog/src/sink/async_sink/async_pool_sink.rs @@ -143,7 +143,7 @@ impl Sink for AsyncPoolSink { // before we do that we have to destroy the thread pool to ensure that any // pending log tasks are completed. self.thread_pool.destroy(); - self.backend.flush() + self.backend.flush_atexit() } } From 3e52f8137a147bb68d33cd4eace1c3bed87f101e Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 4 Oct 2025 00:04:16 +0800 Subject: [PATCH 3/7] forward flush_atexit to DedupSink Signed-off-by: tison --- spdlog/src/sink/dedup_sink.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spdlog/src/sink/dedup_sink.rs b/spdlog/src/sink/dedup_sink.rs index 241f73f3..fac50fb5 100644 --- a/spdlog/src/sink/dedup_sink.rs +++ b/spdlog/src/sink/dedup_sink.rs @@ -158,6 +158,13 @@ impl DedupSink { Error::push_result(result, sink.flush()) }) } + + fn flush_sinks_atexit(&self) -> Result<()> { + #[allow(clippy::manual_try_fold)] // https://github.com/rust-lang/rust-clippy/issues/11554 + self.sinks.iter().fold(Ok(()), |result, sink| { + Error::push_result(result, sink.flush_atexit()) + }) + } } impl GetSinkProp for DedupSink { @@ -186,6 +193,10 @@ impl Sink for DedupSink { fn flush(&self) -> Result<()> { self.flush_sinks() } + + fn flush_atexit(&self) -> Result<()> { + self.flush_sinks_atexit() + } } impl Drop for DedupSink { From 6cb4df9cef007a956373435f1392eb45ad74ee2e Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 4 Oct 2025 00:06:43 +0800 Subject: [PATCH 4/7] fixup Signed-off-by: tison --- spdlog/src/sink/async_sink/async_pool_sink.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spdlog/src/sink/async_sink/async_pool_sink.rs b/spdlog/src/sink/async_sink/async_pool_sink.rs index ad9d8505..85049e1a 100644 --- a/spdlog/src/sink/async_sink/async_pool_sink.rs +++ b/spdlog/src/sink/async_sink/async_pool_sink.rs @@ -266,6 +266,14 @@ impl Backend { result } + fn flush_atexit(&self) -> Result<()> { + let mut result = Ok(()); + for sink in &self.sinks { + result = Error::push_result(result, sink.flush_atexit()); + } + result + } + fn handle_error(&self, err: Error) { self.prop.call_error_handler_internal("AsyncPoolSink", err) } From baa32e9330207a45271ff0eec7a7ab45c7f05881 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 4 Oct 2025 22:14:57 +0800 Subject: [PATCH 5/7] simplify code Signed-off-by: tison --- spdlog/src/logger.rs | 20 +++++++++---------- spdlog/src/sink/async_sink/async_pool_sink.rs | 14 ++++++------- spdlog/src/sink/dedup_sink.rs | 14 ++++++------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/spdlog/src/logger.rs b/spdlog/src/logger.rs index 3ee97138..944e3ee6 100644 --- a/spdlog/src/logger.rs +++ b/spdlog/src/logger.rs @@ -470,14 +470,6 @@ impl Logger { }) } - pub(crate) fn flush_sinks_atexit(&self) { - self.sinks.iter().for_each(|sink| { - if let Err(err) = sink.flush_atexit() { - self.handle_error(err); - } - }); - } - // This will lose the periodic flush property, if any. #[must_use] fn clone_lossy(&self) -> Self { @@ -505,14 +497,22 @@ impl Logger { } } - fn flush_sinks(&self) { + fn flush_sinks_with(&self, with: impl Fn(&dyn Sink) -> Result<()>) { self.sinks.iter().for_each(|sink| { - if let Err(err) = sink.flush() { + if let Err(err) = with(&**sink) { self.handle_error(err); } }); } + pub(crate) fn flush_sinks_atexit(&self) { + self.flush_sinks_with(|sink| sink.flush_atexit()); + } + + pub(crate) fn flush_sinks(&self) { + self.flush_sinks_with(|sink| sink.flush()); + } + fn handle_error(&self, err: Error) { self.error_handler.read_expect().call_internal( format!( diff --git a/spdlog/src/sink/async_sink/async_pool_sink.rs b/spdlog/src/sink/async_sink/async_pool_sink.rs index 85049e1a..8187e3cd 100644 --- a/spdlog/src/sink/async_sink/async_pool_sink.rs +++ b/spdlog/src/sink/async_sink/async_pool_sink.rs @@ -258,20 +258,20 @@ impl Backend { result } - fn flush(&self) -> Result<()> { + fn flush_with(&self, with: impl Fn(&dyn Sink) -> Result<()>) -> Result<()> { let mut result = Ok(()); for sink in &self.sinks { - result = Error::push_result(result, sink.flush()); + result = Error::push_result(result, with(&**sink)); } result } + fn flush(&self) -> Result<()> { + self.flush_with(|sink| sink.flush()) + } + fn flush_atexit(&self) -> Result<()> { - let mut result = Ok(()); - for sink in &self.sinks { - result = Error::push_result(result, sink.flush_atexit()); - } - result + self.flush_with(|sink| sink.flush_atexit()) } fn handle_error(&self, err: Error) { diff --git a/spdlog/src/sink/dedup_sink.rs b/spdlog/src/sink/dedup_sink.rs index fac50fb5..f2bc06ee 100644 --- a/spdlog/src/sink/dedup_sink.rs +++ b/spdlog/src/sink/dedup_sink.rs @@ -152,18 +152,18 @@ impl DedupSink { }) } - fn flush_sinks(&self) -> Result<()> { - #[allow(clippy::manual_try_fold)] // https://github.com/rust-lang/rust-clippy/issues/11554 + fn flush_with(&self, with: fn(&dyn Sink) -> Result<()>) -> Result<()> { self.sinks.iter().fold(Ok(()), |result, sink| { - Error::push_result(result, sink.flush()) + Error::push_result(result, with(sink.as_ref())) }) } + fn flush_sinks(&self) -> Result<()> { + self.flush_with(|sink| sink.flush()) + } + fn flush_sinks_atexit(&self) -> Result<()> { - #[allow(clippy::manual_try_fold)] // https://github.com/rust-lang/rust-clippy/issues/11554 - self.sinks.iter().fold(Ok(()), |result, sink| { - Error::push_result(result, sink.flush_atexit()) - }) + self.flush_with(|sink| sink.flush_atexit()) } } From e37ae9ff34b4d03caf01cd976fa1dcc779a680e5 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 4 Oct 2025 22:20:56 +0800 Subject: [PATCH 6/7] carry out clippy workaround Signed-off-by: tison --- spdlog/src/formatter/mod.rs | 1 - spdlog/src/sink/dedup_sink.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/spdlog/src/formatter/mod.rs b/spdlog/src/formatter/mod.rs index aa048ed3..cfe23162 100644 --- a/spdlog/src/formatter/mod.rs +++ b/spdlog/src/formatter/mod.rs @@ -86,7 +86,6 @@ pub(crate) use journald_formatter::*; pub use json_formatter::*; pub(crate) use local_time_cacher::*; pub use pattern_formatter::*; -pub(crate) use unreachable_formatter::*; use crate::{Record, Result, StringBuf}; diff --git a/spdlog/src/sink/dedup_sink.rs b/spdlog/src/sink/dedup_sink.rs index f2bc06ee..21b373b1 100644 --- a/spdlog/src/sink/dedup_sink.rs +++ b/spdlog/src/sink/dedup_sink.rs @@ -153,6 +153,7 @@ impl DedupSink { } fn flush_with(&self, with: fn(&dyn Sink) -> Result<()>) -> Result<()> { + #[allow(clippy::manual_try_fold)] // https://github.com/rust-lang/rust-clippy/issues/11554 self.sinks.iter().fold(Ok(()), |result, sink| { Error::push_result(result, with(sink.as_ref())) }) From 1e4304a3b7b3b361836c667d0830f8588ba3a273 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 4 Oct 2025 22:24:30 +0800 Subject: [PATCH 7/7] fixup Signed-off-by: tison --- spdlog/src/formatter/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/spdlog/src/formatter/mod.rs b/spdlog/src/formatter/mod.rs index cfe23162..aa048ed3 100644 --- a/spdlog/src/formatter/mod.rs +++ b/spdlog/src/formatter/mod.rs @@ -86,6 +86,7 @@ pub(crate) use journald_formatter::*; pub use json_formatter::*; pub(crate) use local_time_cacher::*; pub use pattern_formatter::*; +pub(crate) use unreachable_formatter::*; use crate::{Record, Result, StringBuf};