fix: use Box<dyn Write + Send> for cross-platform tracing writer

Replace platform-specific std::os::unix::io::FromRawFd with
Box<dyn std::io::Write + Send> return type. This compiles on
Windows, macOS, and Linux without unsafe code.

The closure now returns a boxed writer that is either:
- The cloned file handle (success case)
- A reopened file handle (clone failed)
- stderr (last resort, prevents panic)
This commit is contained in:
huqiantao
2026-06-07 19:35:59 +08:00
parent 4304c89d65
commit 27ca87251e
+15 -13
View File
@@ -157,21 +157,23 @@ pub fn init() -> Result<TuiLogGuard> {
let log_path_clone = log_path.clone();
let subscriber = tracing_subscriber::registry().with(env_filter).with(
fmt::layer()
.with_writer(move || {
.with_writer(move || -> Box<dyn std::io::Write + Send> {
// Clone the file handle for each write. If clone fails (fd exhaustion),
// fall back to reopening the same path, or ultimately stderr.
subscriber_file.try_clone().unwrap_or_else(|e| {
tracing::warn!("Failed to clone log file handle: {e}, reopening");
std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&log_path_clone)
.unwrap_or_else(|_| {
// Last resort: wrap stderr as a File to prevent panic.
use std::os::unix::io::FromRawFd;
unsafe { std::fs::File::from_raw_fd(2) }
})
})
match subscriber_file.try_clone() {
Ok(f) => Box::new(f),
Err(e) => {
tracing::warn!("Failed to clone log file handle: {e}, reopening");
match std::fs::OpenOptions::new()
.create(true)
.append(true)
.open(&log_path_clone)
{
Ok(f) => Box::new(f),
Err(_) => Box::new(std::io::stderr()),
}
}
}
})
.with_ansi(false)
.with_target(true)